【数据结构与算法】第2篇:C语言核心机制回顾(一):指针、数组与结构体

一、写在前面

上一篇我们把环境搭好了,这一篇开始,花两三篇的时间把C语言里和数据结构最相关的知识点过一遍。

如果你已经对指针、结构体很熟了,这篇可以快速浏览,当个复习。但如果这些概念还模糊,建议耐心看完,因为后面的链表、树全都要靠它们。


二、指针:C语言的灵魂

2.1 什么是指针

指针就是一个变量,它存的是地址,不是具体的数值。

c

复制代码
int a = 10;
int *p = &a;  // p存的是a的地址

画个图理解一下:

text

复制代码
变量a:  [10]    地址假设是 0x1000
指针p:  [0x1000] 地址假设是 0x2000

p里面存的是0x1000,通过*p就能找到a,拿到10。

2.2 指针的运算

指针的加减运算,不是简单的地址加1,而是加上它所指向类型的大小。

c

复制代码
int arr[] = {10, 20, 30, 40};
int *p = arr;  // p指向arr[0]

printf("%p\n", p);    // 假设输出 0x1000
printf("%p\n", p+1);  // 输出 0x1004,因为int占4字节

关键点:

  • p+1 跳过了4个字节,指向了arr[1]

  • p++ 也是同样的效果,指针向后移动一个元素

这个特性特别重要,后面遍历数组、操作链表节点全靠它。

2.3 指针和数组的关系

数组名在很多情况下可以当作指针用,但它们不完全一样。

c

复制代码
int arr[5] = {1, 2, 3, 4, 5};
int *p = arr;

printf("%d\n", arr[2]);   // 输出3
printf("%d\n", p[2]);     // 也是3,p可以像数组一样用
printf("%d\n", *(arr+2)); // 也是3,arr可以像指针一样用

关键区别:

  • arr是常量,不能改变指向,比如arr++会报错

  • p是变量,可以随意改,比如p++是合法的

访问数组元素的本质:arr[i] 其实等价于 *(arr + i)。


三、结构体:自定义数据类型

3.1 基本用法

结构体可以把多个不同类型的数据打包在一起。

c

复制代码
struct Student {
    char name[20];
    int age;
    float score;
};

// 使用
struct Student s1 = {"张三", 20, 85.5};
printf("%s的分数是%.1f\n", s1.name, s1.score);

3.2 结构体指针

操作结构体时,经常用指针,因为传指针比传整个结构体效率高。

c

复制代码
struct Student s1 = {"李四", 21, 90.0};
struct Student *p = &s1;

// 两种访问方式
printf("%s\n", (*p).name);   // 写法麻烦,不常用
printf("%s\n", p->name);     // 箭头操作符,推荐

记住 :p->name 等价于 (*p).name。

3.3 内存对齐(重点)

这是一个容易踩坑的点。结构体的大小不是成员大小的简单相加。

c

复制代码
struct Example1 {
    char c;   // 1字节
    int i;    // 4字节
};

printf("%d\n", sizeof(struct Example1));  // 输出8,不是5

为什么是8?因为编译器会做内存对齐:

  • char c占1字节,但为了int i对齐到4字节边界,c后面会空出3个字节(填充)

  • 最终占1+3+4 = 8字节

c

复制代码
struct Example2 {
    int i;    // 4字节
    char c;   // 1字节
};

printf("%d\n", sizeof(struct Example2));  // 输出8,还是8?

这个也是8,但原因不同:int占4,char占1,整体大小需要是最大成员(4)的倍数,所以补3个字节,还是8。

c

复制代码
struct Example3 {
    char c1;  // 1
    char c2;  // 1
    int i;    // 4
};

printf("%d\n", sizeof(struct Example3));  // 输出8(1+1+2填充+4)

对齐规则:

  1. 每个成员相对于结构体起始地址的偏移量,必须是该成员大小的整数倍

  2. 结构体的总大小,必须是最大成员大小的整数倍

写数据结构时要注意:如果结构体内有指针,指针在64位系统占8字节,对齐会影响整个结构体的大小。


四、typedef:给类型起别名

typedef能让代码更简洁,尤其是后面写链表,不用每次都写struct Node。

c

复制代码
// 不用typedef
struct Node {
    int data;
    struct Node *next;
};
struct Node n1;  // 每次都要写struct

// 用typedef
typedef struct Node {
    int data;
    struct Node *next;
} Node;

Node n1;  // 简洁多了

还有一种写法更常见:

c

复制代码
typedef struct Node {
    int data;
    struct Node *next;
} Node, *PNode;  // PNode是指向Node的指针类型

Node n1;
PNode p = &n1;   // p是Node*类型

五、一个综合例子

把前面学的串起来,定义一个学生结构体,用指针操作:

c

复制代码
#include <stdio.h>
#include <string.h>

typedef struct Student {
    char name[20];
    int age;
    float score;
} Student;

void printStudent(Student *p) {
    printf("姓名:%s,年龄:%d,分数:%.1f\n", 
           p->name, p->age, p->score);
}

int main() {
    Student s1;
    strcpy(s1.name, "王小明");
    s1.age = 19;
    s1.score = 88.5;
    
    Student *p = &s1;
    printStudent(p);
    
    // 演示指针运算(数组)
    Student class[3] = {
        {"张三", 20, 85},
        {"李四", 21, 90},
        {"王五", 19, 87}
    };
    
    Student *q = class;
    printf("第一个学生:%s\n", q->name);
    printf("第二个学生:%s\n", (q+1)->name);  // 指针移动
    
    return 0;
}

输出:

text

复制代码
姓名:王小明,年龄:19,分数:88.5
第一个学生:张三
第二个学生:李四

六、小结

这一篇讲了三个核心概念:

概念 要点
指针 存地址,加减运算跳过的字节数取决于指向的类型
数组 数组名可当指针用,但是常量不能改指向
结构体 自定义类型,大小要考虑内存对齐
typedef 简化类型名,让代码更简洁

这些是写数据结构的基石,下一篇我们会讲动态内存分配(malloc和free),学会之后就可以开始手写链表了。


七、思考题

  1. 下面的结构体占多少字节?(假设是32位系统,指针4字节)

c

复制代码
typedef struct {
    char a;
    int *p;
    char b;
} Test;
  1. 为什么结构体要有内存对齐?不直接按顺序存?
相关推荐
重生之小比特1 分钟前
【算法拾光】二分查找|二分查找 + 再排序数组中查找元素的第一个和最后一个位置
算法·leetcode·职场和发展
学逆向的2 分钟前
C printf原型解析
c语言·开发语言·网络安全
纪念 2293 分钟前
C++ list讲解
c++·windows·list
\光辉岁月/4 分钟前
5.math类
java·开发语言
不像程序员的程序媛12 分钟前
mybatisplus insert dto未指定id时会如何
java·开发语言
闻缺陷则喜何志丹19 分钟前
vc入门宝典(九)
数据结构·list·mfc·存储·null·class
BeiGuTing_code28 分钟前
C字符输出:一个换行符引发的“失踪案”
c语言·开发语言
零基础12330 分钟前
基于模型的强化学习与不基于模型的强化学习:核心区别与实战选择
python·算法
我命由我1234532 分钟前
5-2.Python 编码进阶 - 字符串进阶(拼接、普通格式化、普通格式化数字精度控制、快速格式化、遍历、常用方法)
java·开发语言·后端·python·学习·java-ee·学习方法
http阿拉丁神猫5 小时前
Go语言入门笔记:从基础到开发环境搭建(二)
开发语言·笔记·golang