结构体的大小是多少
任意给定一个结构体,它的大小是多少?
结构体的大小,由两部分组成:成员的大小 + 成员之间的空隙
字节对齐决定了结构体成员之间的空隙大小
字节对齐
结构体字节对齐有2个规则:
- 成员的偏移是成员大小的整数倍,这个规则会在成员之间插入空隙
- 结构体的总大小是最大成员大小的整数倍,这个规则会在结构体末尾插入空隙。此时,对齐系数就是最大成员的大小。
解释:第二条规则主要用于结构体组成数组的情况,数组的成员之间就不用再插入空隙了
注:
- 如果结构体成员里有数组,在对齐时当成多个成员来对待
- 如果制定了对齐系数:
#pragma pack(n),其中n = 1, 2, 4, 8, 16- 成员的偏移:取成员大小和
n中较小的那个数,成员偏移是其整数倍 - 结构体的总大小:取最大成员大小和
n中较小的那个数,结构体的大小是其整数倍。此时,对齐系数就是两者中的较小值。
- 成员的偏移:取成员大小和
如图所示:
如果结构体里面有结构体,那么视内部结构体的对齐系数是其最大元素的对齐系数。
如果需要跨进程传递结构体,需要保证 pack(1) 和 pack(4) 得到的成员偏移是相同的;如果含有 64 位成员,需要保证 pack(1) 和 pack(8) 成员偏移是一样的。
上述条件可以通过将成员按从大到小的顺序排列达成。这种排列方式,成员之间一定不会出现空隙。(如果成员里面有结构体,需要谨慎考虑)
结构体的起始地址是多少
结构体的起始地址,也存在对齐:
- 如果没有设置
#pragma pack(n),就取结构体中最大的成员长度作为对齐系数,结构体首地址是其整数倍 - 如果设置了
#pragma pack(n),就取最大成员长度和n中较小的数作为对齐系数
对齐规则,对一般数据也起作用
如图所示:(在 fedora-x86_64-gcc 环境下得到的结果)
常见类型大小
# 整形short # 2int # 4long # 不确定的long long # 8# 字符char # 1# 浮点float # 4double # 8# 指针大小void* # 32位是4,64位是8
有符号与无符号:
char # 不能确定是有符号还是无符号的short # signedint # signedlong # signedlong long # signed
