C语言struct字节对齐问题

一、总结

1.1 先确定实际对齐单位,其由以下三个因素决定

(1) CPU周期

WIN vs qt 默认8字节对齐

Linux 32位 默认4字节对齐,64位默认8字节对齐

(2) 结构体最大成员(基本数据类型变量)

(3) 预编译指令#pragma pack(n)手动设置 n–只能填1 2 4 8 16

上面三者取最小的,就是实际对齐单位

1.2相对于结构体地址的偏移量

除结构体的第一个成员外,其他所有的成员的地址相对于结构体地址(即它首个成员的地址)的偏移量必须为实际对齐单位或自身大小的整数倍(取两者中小的那个)

大多数处理器要求对某些类型的变量进行特定的内存对齐。通常,最小对齐方式是所讨论的基本类型的大小,例如

(1) char 变量可以按字节对齐,并且可以出现在任何字节边界

(2) short(2字节)变量必须对齐2个字节,它们可以出现在任何偶数字节边界。这意味着0x10004567不是short变量的有效位置,而0x10004566是有效位置。

(3) long(4字节)变量必须对齐4字节,它们只能出现在4字节倍数的字节边界上。这意味着0x10004566不是长变量的有效位置,而0x10004568是有效位置。

之所以会出现结构成员对齐,是因为结构的成员必须出现在正确的字节边界处,为此,编译器会放入填充字节(如果使用位字段,则填充位),以便结构成员出现在正确的位置。

1.3结构体的整体大小必须为实际对齐单位的整数倍。

另外,结构的大小必须使得在结构的数组中,所有结构在内存中都正确对齐,因此结构的末尾也可能存在填充字节

二、测试验证

2.1 T1

struct test1
{							实际地址		  偏移量
	uint16_t  a;		//0x24048864		0	  地址为2的倍数
	uint8_t   b;		//0x24048866		2	  地址为1的倍数
	uint32_t  c;		//0x24048868		4     地址为4的倍数
	uint8_t   d;		//0x2404886C		8     地址为1的倍数
	uint16_t  e;		//0x2404886E		10    地址为2的倍数
	uint8_t   f;		//0x24048870		12    地址为1的倍数
	uint32_t  g;		//0x24048874		16    地址为4的倍数
	uint8_t   h;		//0x24048878		20    地址为1的倍数
};
struct test1 t1 = {0};
sizeof(t1) 值为24   
t1.b后填充了1个字节
t1.d后填充了1个字节
t1.f后填充了3个字节
t1.h后填充了3个字节
对齐单位为 4 字节

0x640x660x680x6c0x6e0x700x740x78
aabccccdeefggggh

2.2 T2

#pragma pack(4)			//设置4字节对齐,但实际上由于结构体中单个成员的
						//最大占用字节数为2字节,因此实际还是按2字节对齐
struct test2
{							实际地址		  偏移量
	uint8_t  a;			//0x24048874		0	  地址为1的倍数
	uint8_t   b;		//0x24048875		1	  地址为1的倍数
	uint16_t  c;		//0x24048876		2     地址为2的倍数
	uint8_t   d;		//0x24048878		4     地址为1的倍数
};

struct test2 t2 = {0};
sizeof(t2) 值为6  
t2.d后填充了1个字节
对齐单位为 2 字节

0x740x750x760x78
abccd

————————————————
参考链接1:
https://blog.csdn.net/m0_37829435/article/details/81348532
参考链接2:
https://bytes.com/topic/c/answers/543879-what-structure-padding

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值