struct 不是什数一种“数据类型”,准确说,据类它是什数 C 家族语言里用来打包多个变量的关键字。你写
struct Person { char name[20]; int age; };,据类编译器不会给你一个能直接存进 CPU 寄存器的什数值,它给的据类是一块内存布局图。Person 本身不是什数类型,struct Person才是据类。很多人第一次学的什数时候会卡在这:为什么声明变量要写struct Person p1;,不能直接Person p1;?据类因为 C 里 struct 标签和类型名分属两个命名空间,除非你 typedef,什数否则就得带着 struct 走。据类拿个具体例子。什数我写过一个解析二进制协议的据类小工具,报文头固定 8 字节:2 字节魔数、什数1 字节版本、1 字节类型、4 字节长度。用 struct 定义出来就是:
struct Header { uint16_t magic; uint8_t version; uint8_t type; uint32_t length; };这玩意儿看起来简单,但坑不少。编译器可能在 magic 和 length 之间插入填充字节,让 length 对齐到 4 字节边界。结果
sizeof(struct Header)不是 8,而是 12。你直接fread读 8 字节进去,length 字段就错位了。解决办法要么加__attribute__((packed)),要么手动按字节解析。我见过有人在这上面栽跟头,调试了一下午,最后发现是结构体对齐搞的鬼。另一个常被忽略的点:struct 可以嵌套,也可以包含指向自身的指针。链表节点就是典型:
struct Node { int value; struct Node *next; };这里
next是指针,大小固定,所以 struct Node 的大小是可计算的。如果写成struct Node next;,那就是无限递归,编译器直接报错。指针在这里是“打破递归”的关键。我刚开始学数据结构时,总觉得链表节点里放一个同类型的变量很自然,后来才明白,放指针和放变量完全是两码事。struct 在内存里的布局还受编译器影响。同一个 struct,在 GCC 和 MSVC 下可能大小不同,字段顺序也可能被重排——当然标准不保证顺序,但大多数编译器按声明顺序排。如果你要做跨平台的数据交换,别直接把 struct 二进制写进文件或网络包。我一般会写序列化函数,逐字段转成网络字节序,而不是
memcpy整个结构体。吃过亏:x86 上跑得好好的,搬到 ARM 上就崩了,因为对齐要求不一样。还有一点,struct 可以按值传递,也可以按指针传递。按值传递会拷贝整个结构体,如果结构体很大,比如里面有个 1KB 的数组,每次函数调用都拷一遍,性能直接跪。我习惯超过 16 字节就传指针,除非明确需要值语义。C++ 里 struct 和 class 几乎一样,区别只是默认访问权限,但那是另一个话题了。
总结一下我的观察:struct 是内存布局工具,不是抽象数据类型。它不提供封装、继承、多态,只负责把一堆变量捆在一起,让你能用一块连续内存表示一个逻辑单元。理解它的关键在于理解内存对齐、指针和值语义。写底层代码时,struct 用得好不好,直接决定程序是跑得飞起还是莫名其妙崩溃。
顶: 4踩: 9892






评论专区