计算结构体所占用的内存是在学习C语言时需要学习的内容,学习结构体内存对齐是计算结构体所占空间必不可少的知识点。
那么什么是结构体内存对齐呢?相信学完这篇文章后,你会对结构体有更加深入的理解。
对齐规则
1. 结构体的第⼀个成员对⻬到和结构体变量起始位置偏移量为0的地址处。 2. 其他成员变量要对⻬到某个数字(对⻬数)的整数倍的地址处。 对⻬数 = 编译器默认的⼀个对⻬数与该成员变量⼤⼩的较⼩值。- - VS 中默认的值为 8
- - Linux中 gcc 没有默认对⻬数,对⻬数就是成员⾃⾝的⼤⼩
练习
下面让我们通过几个练习来了解上面结构体的对齐规则。
练习1
为了方便计算,我们画了一个图,图中一个格子代表一个字节。
如上图所示,从偏移量为0的位置开始存放,由于结构体中的第一个成员变量是char c1,所以占一个字节,从第二个结构体成员变量开始,内存要对齐到对齐数的整数倍处,由于我们使用的编译器是VS,且VS默认的对齐数是8个字节,且成员变量的对齐数等于编译器的默认对齐数与成员变量所占空间大小的最小值,且第二个成员变量为int类型,占4个字节,所以第二个成员变量的对齐数是4,以此类推,第三个成员变量的对齐数是1,整个结构体的总大小为4的倍数,即结构体总大小为12个字节。
所以输出结果为12个字节,如下图:
练习2
为了方便计算,我们画了一个图,图中一个格子代表一个字节。
如上图所示,从偏移量为0的位置开始存放,由于结构体中的第一个成员变量是double d,所以占8个字节,从第二个结构体成员变量开始,内存要对齐到对齐数的整数倍处,由于我们使用的编译器是VS,且VS默认的对齐数是8个字节,且成员变量的对齐数等于编译器的默认对齐数与成员变量所占空间大小的最小值,且第二个成员变量为char类型,占1个字节,所以第二个成员变量的对齐数是1,以此类推,第三个成员变量的对齐数是4,整个结构体的总大小为8的倍数,即结构体总大小为16个字节。
所以输出结果为16个字节,如下图:
练习3
为了方便计算,我们画了一个图,图中一个格子代表一个字节。
如上图所示,从偏移量为0的位置开始存放,由于结构体中的第一个成员变量是char c1,所以占1个字节,从第二个结构体成员变量开始,内存要对齐到对齐数的整数倍处,由于我们使用的编译器是VS,且VS默认的对齐数是8个字节,且成员变量的对齐数等于编译器的默认对齐数与成员变量所占空间大小的最小值,且第二个成员变量为结构体类型,结构体成员中的最大对齐数占8个字节,所以第二个成员变量的对齐数是8,以此类推,第三个成员变量的对齐数是8,整个结构体的总大小为8的倍数,即结构体总大小为32个字节。
所以输出结果为32个字节,如下图:
修改默认对齐数
其实,在VS编译器中,我们的默认对齐数是可以修改的,只需要用到#pragma 这个预处理指令,可以改变编译器的默认对⻬数。
例如:
从练习1中我们可以知道如果默认对齐数为8时,这个结构体的对齐数为12,如果将默认对齐数修改为1呢?这个结构体的对齐数是否为变为6,答案是肯定的。
输出结果为:
修改默认对齐数的代码为#pragma pack(想要设置的对齐数),需要注意的是,当用完后,需要用代码#pragma pack()取消自己设置的默认对齐数。