C语言——结构体的内存存储规则

一、引言

cpp 复制代码
struct stu1
{
	char a;
	short b;
	int c;
};
struct stu2
{
	char a;
	int c;
	short b;
};

int main()
{
	//输出结构体所占字节大小
	printf("%d\n", sizeof(struct stu1));  // 结果:8
	printf("%d\n", sizeof(struct stu2));  // 结果:12
}

在 C 语言中定义结构体时,成员变量顺序不同,最终结构体占用的内存大小也不同 ,并非简单把所有成员字节数相加。这背后就是结构体内存对齐机制。

二、内存对齐核心思想

(一)为什么要内存对齐

计算机CPU访问内存数据时,不会零散逐字节读取,而是优先以2的整数倍字节批量访问,常见为2Byte、4Byte、8Byte,以此提升读写效率。

内存对齐是为了让每一个成员的内存尽可能保持对齐,这样CPU一次访问的字节数,就可以直接完整取到这个元素。

核心思想:用空间换取访问时间效率

(二)内存对齐规则

1.第一个成员在与结构体变量偏移量为0的地址处

2.其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处

(1)对齐数 = 编译器默认对齐数与该成员大小的较小值

(2)VS环境下默认对齐数是8

3.结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍

4.如果是嵌套结构体

(1)嵌套的结构体对齐到自己的最大对齐数的整数倍处

(2)结构体整体大小就是"所有最大对齐数(含嵌套的对齐数)"的整数倍

cpp 复制代码
struct stu1
{
	char a;		// 偏移 0,占用 1 字节 -> 【0】
    			// 偏移 1,"浪费 1 字节"(为了对齐)
	short b;	// 对齐数:min(2, 8) = 2
    			// 从偏移 2 开始,占用 2 字节 -> 【2, 3】
	int c;		// 对齐数:min(4, 8) = 4
    			// 从偏移 4 开始,占用 4 字节 -> 【4, 5, 6, 7】
};	

// 总大小:8 Byte
// 校验:8 % 最大对齐数(4) == 0,满足规则!
cpp 复制代码
struct stu2
{
	char a; 	// 偏移 0,占用1字节   【0】
         		// 偏移 1、2、3,浪费3字节(对齐填充)
	int c;		// 对齐数:min(4, 8) = 4
         		// 偏移 4 开始,占用4字节 【4,5,6,7】
	short b;	// 对齐数:min(2, 8) = 2
         		// 偏移 8 开始,占用2字节 【8,9】
};	

// 当前总长度:10 Byte
// 校验:10 % 最大对齐数(4) != 0,不满足规则!
// 自动填充字节,补齐到 12 Byte

(三)手动修改默认对齐数

cpp 复制代码
#pragma pack(n)    // 设置默认对齐数为 n(n 只能是 1、2、4、8、16)
#pragma pack()     // 取消手动设置,恢复编译器默认(VS 默认 8)
相关推荐
敲代码的瓦龙1 小时前
Android?广播!!!
android·java·开发语言·android-studio
磊 子1 小时前
1.2内存的存储金字塔
java·开发语言·spring·操作系统
wjs20241 小时前
Bootstrap5 提示框(Tooltip)
开发语言
逆境不可逃1 小时前
Hello-Agents 第二部分-第四章总结:智能体经典范式构建-包含习题解析和Java版
java·开发语言·javascript·人工智能·分布式·agent
springXu1 小时前
windows arm64上的VS CODE的GoLang环境的搭建
开发语言·后端·golang
ChoSeitaku1 小时前
08_抽象_接口_final关键字_多态
java·开发语言
程序员zgh1 小时前
AUTOSAR CP 之 配置、开发流程、工具链 解析
c语言·开发语言·c++·系统架构·汽车
xyq20241 小时前
Bootstrap4 提示框
开发语言
yqcoder1 小时前
JavaScript 的速度秘密:深入理解 JIT (即时编译)
开发语言·javascript·ecmascript