资讯动态

16.结构体大小

发布时间:2026/10/9 7:41:38 来源:尧图企业网站定制
前置必懂指针大小区分X86 / X64 X86 (32 位环境)地址编号 32 位 → 所有指针占 4 字节 X64 (64 位环境)地址编号 64 位 → 所有指针占 8 字节int、double、结构体指针、数组指针不管指向谁指针本身大小全都一样。补充指针类型决定的是指针加减时的步长不决定指针本身占用字节。一、结构体 内存对齐核心重点内存对齐 4 条黄金规则必须背第一个成员放在偏移量为 0 的地址。其余成员要对齐到对齐数的整数倍地址。 对齐数 min (编译器默认对齐数当前成员所占字节大小) VS 默认对齐数 8结构体总大小必须是本结构体最大对齐数的整数倍不够就补空闲填充字节浪费的空间也叫填充字节 / 补丁。如果结构体里面嵌套另一个结构体嵌套结构体要对齐到「它自己的最大对齐数」的整数倍地址最外层结构体总大小是全部成员 (含嵌套结构体) 最大对齐数的整数倍。为什么要有内存对齐 CPU 读取内存是整块读取一次读 4 字节 / 8 字节。 对齐以后CPU 读取一个成员只需要读 1 次内存不对齐就需要读 2 次内存再拼接数据。 用少量空闲内存换取更快的访问速度。空间换时间。例题讲解struct stu1 { char a; //1字节 short b; //2字节 int c; //4字节 };偏移计算 a偏移 0占 1 字节0 号地址 b对齐数 min (8,2)2地址必须是 2 倍数 → 偏移 2占用 2‑3 c对齐数 min (8,4)4地址必须 4 倍数 → 偏移 4占用 4‑7 已占用到 7 号地址。最大对齐数 4。 总大小 8是 4 的倍数。 sizeof (struct stu1) 8struct stu2 { char a; //1 int c; //4 short b; //2 };a偏移 0占用 0 c对齐数 4偏移 4占用 4‑7 b对齐数 2偏移 8占用 8‑9 目前用到 9 号地址。最大对齐数 4。 总大小必须是 4 倍数9 往后最近的 4 倍数就是 12。 sizeof (struct stu2)12修改默认对齐数#pragma pack(n)n 只能填 1,2,4,8,16 作用把编译器默认对齐数临时改成 n。 对齐数公式变为对齐数 min (n , 成员字节大小)例#pragma pack(4) struct stu7 { int a; //4 0~3 char b; //1 4 double c; //8min(4,8)4对齐数4 →偏移88‑15 };用到 15总大小 16是最大对齐数 4 的倍数。sizeof16。二、位段结构体的进阶玩法节省内存基础格式struct 名字 { 整型类型 成员名 : 位数; };位数代表这个成员占用多少个二进制位 (bit)不是字节 1 字节 8 bit示例struct Test { unsigned int a : 4; //占用4个比特位 unsigned int : 2; //无名位段占位这2个位不能使用 unsigned int b : 6; //占用6个比特位 };两个特殊位段 0 位段unsigned int : 0;剩下没用完的空位直接舍弃强制下一个成员放到一块全新的存储单元。无名位段只有冒号和位数没有成员名。用来填充空位、对齐这块空间永远不能读写。位段硬性限制小白必背坑成员类型只能是整型家族int /unsigned int /signed intchar 少数编译器支持但不推荐不能写浮点。单个成员冒号后面的位数不能超过它本身类型的总比特数int 最多写32。不能对位段成员取地址a。地址是按字节编号位是字节里面拆分出来的没有独立地址。不能做成数组a[3]:2语法报错。n 位无符号数取值范围0 ~ 2ⁿ‑1有符号‑2ⁿ⁻¹ ~ 2ⁿ⁻¹‑1。赋值超出范围高位截断数据出错。补充位段内部 bit 排布大端 / 小端C 标准没有规定不同编译器结果不同。考试只考上面 5 条规则不考 bit 内部顺序。 优点存放大量小范围标记数据大幅节省内存空间。 缺点不可跨平台工程开发慎用。三、枚举 enum一组有关系的整型常量基础语法enum 枚举名 { 元素1, 元素2, 元素3 };默认规则第一个元素默认值 0往后依次 1。enum Week { Mon, //0 Tue, //1 Wed //2 };手动赋值enum Color { red2, green, //自动1 → 3 blue6, yellow //自动1 →7 };定义变量两种写法 写法 1后面定义推荐int main() { enum Week day; day Mon; }写法 2定义枚举类型的时候顺便创建变量enum Sex { man, woman } s1,s2;typedef 简化typedef enum { open, close }Status; int main() { Status st open; }枚举核心特性枚举里面的元素都是常量不能修改值。枚举变量本质就是 int可以做加减运算、比较大小。C 语言语法允许给枚举变量随便赋一个整数但逻辑上不推荐破坏枚举本意。优先用 enum 代替#define定义常量枚举调试更方便可读性更强。四、联合共用体 union【高频易混和结构体区分】核心本质所有成员共用同一块内存空间同一时刻只能使用其中 1 个成员。一个赋值其余成员数据立刻被覆盖。语法格式union 联合名 { 成员1; 成员2; 成员3; };示例union Data { int i; float f; char c; };大小计算规则 联合所占字节大小 联合里面最大成员的字节大小 ⚠但是还要对齐联合的总大小必须是最大对齐数的整数倍。例union Data { char c; // 1字节 int i; // 4字节 };最大成员 4 字节sizeof (union Data)4。补充例子union Test { char arr[5]; //5字节 int i; //4字节 };最大成员 5 字节最大对齐数 4向上取最近 4 的倍数sizeof8。使用演示union Data d; d.i 10; //现在这块内存存整数 printf(%d, d.i); d.c A; //覆盖原来i的数据 printf(%c, d.c);结构体 VS 联合对比表表格类型内存关系内存大小struct 结构体所有成员各自独立互不干扰同时共存所有成员空间相加 对齐填充字节union 联合所有成员共用一块内存互斥使用最大成员大小 (还要对齐)五、匿名结构体普通结构体带名字可以反复创建变量struct Student { int age; }; struct Student s1; struct Student s2;匿名结构体struct 后面不写结构体名字struct { int age; char name[20]; } stu; //定义的时候必须立刻写上变量名匿名结构体三条铁律struct 后面没有类型名字只能在定义的那一行直接创建变量后面不能再拿这个类型定义新变量。只能一次性使用不能复用。最常见用法嵌套在另一个结构体里面struct Person { int id; struct { int year; int month; } birthday; }; //访问方式 struct Person p; p.birthday.year 2000;struct /union/ 位段 /enum 汇总对比表格类型内存特点核心考点struct 结构体成员独立同时共存内存相加 对齐填充内存对齐sizeof 计算union 联合成员共用同一块内存互斥使用共用内存sizeof 取最大成员并对齐位段在整型内部拆分 bit 位节省空间不能取地址、位数限制、不能跨平台enum 枚举一组整型常量不是变量默认从 0 自增元素是常量刷题坑汇总指针本身大小只看 32/64 位平台和指针指向什么类型无关指针类型决定1跳多少字节。内存对齐计算两步先算每个成员偏移最后结构体总大小要等于最大对齐数整数倍。#pragma pack(n)只对当前编译单元临时生效n 推荐 1/2/4/8/16。位段不能取地址不能做数组位数不能超过基础类型总 bit。union 所有成员共用内存修改一个其他成员值被覆盖。匿名结构体定义时必须紧跟变量名后面不能重复使用这个类型。枚举成员是常量不能赋值修改枚举变量本质是整型。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑