目录
发现问题
有以下两个结构体:
结构体1:
struct S1
{
char c1; // 1字节
int i; // 4字节
char c2; // 1字节
};
结构体2:
struct S2
{
char c1; // 1字节
char c2; // 1字节
int i; // 4字节
};
通常情况下:结构体1的大小是6字节(char是1字节 + int是4字节 + char是1字节);结构体2的大小是6字节(char是1字节 + char是1字节 + int是4字节)
打印结构验真假:
打印发现 结构体1 和 结构体2 所占内存空间的大小并不一样,出现这种结果的原因是因为结构体内存对齐规则的原因,利用宏 offsetof() 可以帮助判断
偏移量宏:offsetof()
offsetof() 这个宏可以计算结构体成员相较于结构体起始位置的偏移量
头文件为:#include<stddef.h>
计算结构体所有成员对于结构体起始位置的偏移量:
struct S1
{
char c1;
int i;
char c2;
};
int main()
{
printf("%d", offsetof(struct S1, c1));
printf("%d", offsetof(struct S1, i));
printf("%d", offsetof(struct S1, c2));
return 0;
}
计算结果:
可以发现,c1 是char类型的变量,所占内存空间只有1个字节,且是第一个变量,所以放在结构体起始位置偏移量为0的地方,那为什么第二个变量要放在离起始位置偏移量4的地方,中间的3个字节为什么要浪费掉?
由以上问题分析得出,结构体成员不是按照顺序在内存中连续存放的,是有一定的对齐规则
结构体内存的对齐规则
1. 结构体的第一个成员永远放在相较于结构体起始位置的偏移量为0的位置
2. 从第二个成员开始,往后的每个成员都要对齐到某个对齐数的整数倍处
3. 结构体的总大小,必须是最大对齐数的整数倍,而这最大对齐数也就是结构体所有成员的对齐数中最大的值
对齐数:结构体成员自身的大小和默认对齐数的较小值
默认对齐数:VS编译器上的默认对齐数是8,而gcc这种编译器没有默认对齐数,对齐数就是结构体成员的自身大小
由以上的规则,我们可以得知,为什么第二个变量要放在相较于结构体起始位置的偏移量为4的位置了
再次复盘以上结构体:
struct S1
{
char c1;
int i;
char c2;
};
第一个成员:char类型的c1变量,放在相较于结构体起始位置的偏移量为0的位置
第二个成员:int类型的i变量,i的大小是4个字节,VS中默认对齐数是8,在4和8中取较小值,也就是4,所以第二个成员变量 i 要放在偏移量为4的倍数处,所以成员变量 i 的偏移量是 4
第三个成员:char类型的c2变量,c2 的大小是1个字节,在1和8中取较小值,也就是1,所以第三个成员变量 c2 要存放在偏移量为1的倍数处,且偏移量为4、5、6、7的位置已经被第二个成员所占,所以 c2 存放在偏移量为8的位置
结构体总大小:
printf("%d\n", sizeof(struct S1));
结构体的总大小是最大对齐数的整数倍,由以上第二个成员可得出,最大对齐数是4,所以结构体的总大小必须是4的倍数,而当前结构体的大小是9,因为第三个成员是放在偏移量为8的位置的,且占一个字节,所以一共占了9个字节,9不是4的倍数,所以最4的最小整数倍是12,所以最后整个结构体的总大小是12个字节
小结
除了结构体的第一个成员是放在结构体的起始处位置(也就是相较于结构体起始位置偏移量为0的位置),其他的成员要按照对齐规则存放
且结构体的总大小是结构体成员最大对齐数的整数倍
标签:字节,成员,偏移量,C语言,char,对齐,体内,结构 From: https://blog.csdn.net/weixin_55341642/article/details/141229948