本文最后更新于101 天前,其中的信息可能已经过时,如有错误请发送邮件至 2641805259@qq.com
1. 结构体的概念
结构体(struct)用于将多个不同类型的成员组合成一个整体,以描述复杂数据实体。
示例:
struct Student {
int id;
char name[20];
float score;
};
结构体本质上是“用户自定义的数据类型”。
2. 结构体定义与声明
2.1 结构体类型定义
struct Point {
int x;
int y;
};
2.2 声明结构体变量
struct Point p;
2.3 定义类型别名(推荐)
使用 typedef 简化书写:
typedef struct {
// 结构体成员
int x;
int y;
} Point;
Point p;
3. 结构体的初始化
3.1 顺序初始化
struct Point p = {10, 20};
3.2 指定成员初始化(C99)
struct Point p = {.y = 20, .x = 10};
4. 结构体成员访问
4.1 普通变量通过 .
p.x = 5;
p.y = 8;
4.2 指针变量通过 ->
struct Point *pt = &p;
pt->x = 5;
pt->y = 8;
. 和 -> 的关系:
(*pt).x 等价于 pt->x
(*pt).y 等价于 pt->y
5. 结构体与内存布局
结构体的大小由以下因素影响:
- 成员顺序
- 成员对齐要求
- 编译器填充(padding)
示例:
struct A {
char c; // 1个字节
char d; // 1个字节
int i; // 4个字节
};
可能大小为 8 字节(取决于平台):
- char 占 1 字节
- 后面补 3 字节填充
- int 占 4 字节
大小由:sizeof(struct A) 决定。
6. 结构体与指针
6.1 结构体指针
struct Student s;
struct Student *p = &s;
p->score = 99.5;
6.2 指向结构体成员的指针
int *ptr = &(p->id);
6.3 使用 malloc 动态创建结构体
struct Student *stu = malloc(sizeof(struct Student));
stu->id = 1;
释放:
free(stu);
7. 结构体作为函数参数
7.1 按值传递(会复制结构体)
void print(struct Point p);
适用于小结构体。
7.2 按指针传递(无复制,效率高)
void modify(struct Point *p);
8. 结构体嵌套
8.1 结构体作为成员
struct Date {
int y, m, d;
}; // 结构体的声明和定义
struct Student {
int id;
struct Date birth; // 结构体的调用
};
访问:
s.birth.y = 2000;
8.2 自引用结构体(链表核心)
必须使用指针:
struct Node {
int data;
struct Node *next;
};
9. 结构体数组
struct Point{
int x;
int y;
}
struct Point arr[3] = {
{1,2},
{3,4},
{5,6}
};
访问:
arr[1].x = 10;
10. 位段(Bit-fields)
用于精确指定字段的位数:
struct Flags {
unsigned int a : 1;
unsigned int b : 3;
unsigned int c : 4;
};
常用于嵌入式与通信协议。
11. 结构体与 typedef 的常见组合模式
11.1 基本用法
typedef struct {
int x;
int y;
} Point;
11.2 命名结构体 + typedef
typedef struct Student {
int id;
int age;
} Student;
11.3 自引用链表常见形式
typedef struct Node {
int data;
struct Node *next;
} Node;
12. 结构体内存拷贝
结构体可以整体赋值:
struct Point p1 = {1,2};
struct Point p2 = p1; // 整体拷贝
也可以使用 memcpy:memory copy
memcpy(&p2, &p1, sizeof(p1));
13. 结构体与对齐控制(可选进阶)
#pragma pack(1)
struct A {
char c;
int i;
};
#pragma pack()
强制按 1 字节对齐,可用于通信协议或磁盘格式解析。
14. 枚举(enum)
枚举用于定义一组“有意义的整型常量”,使代码更可读。
14.1 基本定义
enum Color {
RED,
GREEN,
BLUE
};
枚举值默认从 0 开始递增:
RED=0, GREEN=1, BLUE=2
14.2 指定枚举值
enum Status {
OK = 200,
NOT_FOUND = 404,
ERROR = 500
};
14.3 typedef 简化
typedef enum {
MON, TUE, WED, THU, FRI, SAT, SUN
} Weekday;
Weekday w = MON;
14.4 应用场景
- 状态码
- 有限状态机
- 标志值集合
- 选项类型定义
15. 联合体(union)
联合体用于多个成员 共享同一段内存。
特点:
- 所有成员起始地址相同
- 联合体大小 = 最大成员大小
- 每次只能有效使用其中“一个成员”
15.1 定义
union Data {
int i;
float f;
char str[20];
};
15.2 共享内存示例
union Data d;
d.i = 100;
printf("%d\n", d.i);
// 再存 float,会覆盖同一块内存
d.f = 3.14;
printf("%f\n", d.f);
// 读 d.i 是未定义行为
15.3 应用场景
联合体用于高效处理多种可能类型的数据:
- 协议解析(例如一个字节拆为 bit 段)
- 数据类型重解释(类型 punning)
- 嵌入式设备映射寄存器
- 节省内存的结构体复用
15.4 联合体 + 结构体混用(常见)
typedef struct {
int type;
union {
int i;
float f;
char s[20];
} data;
} Variant;
可实现“可变类型结构体”。
( ๑´•ω•) “(ㆆᴗㆆ)