C语言结构体字节对齐的设置 #pragma和__attribute__

最近写蓝牙协议,数据必须按协议中指定的报文进行传输,但由于默认处理器有字节对齐,而一旦多一个字节都会导致通信错误,所以这里记录一下字节对齐的处理。

1 介绍

CPU不会一个字节一个字节地读或写内存,而是一次访问2/4/6/8/16/32/64字节,因为这比读一个字节要快得多。假设CPU按四字节对齐,我们把四字节称为一个chunk,此时要读内存0x03-0x06的内容,CPU就会读取0x00~0x03和0x04-0x07两个chunk,然后把两个chunk读到的内容移位并组合返回给用户。

假设CPU按照4字节进行对齐,现在来看一个结构体:

struct S1{
	char a;
	char b;
};

CPU就会在结构体最后填充两个字节,以保证字节对齐。注意这个对齐不总是在最后的,而是数据类型所对应的变量需要字节对齐,比如

struct S2{
	uint8_t a;
	uint16_t b;
};

由于uint16_t为2字节,需要2字节对齐,而前面的uint8_t只有1字节,故会在a后面填充1个字节,而对于结构体变量S2来说,其需要四字节对齐,故还会在b后面填充一个字节。

  • 变量类型占多少个字节就需要几字节对齐,比如uint8_t为1字节,则它放在内存中任何位置都可以

2 设置字节对齐

2.1 pack注释

我们可以使用pack pragma来设置对于struct、union和class的字节对齐:

1、保存当前系统字节对齐的状态,对指定的结构对齐完恢复原先对齐数
#pragma pack(push, N)
待字节对齐的struct、union和class
#pragma pack(pop)
注:
#pragma pach(push,N)等价于
#pragma pack(push)
#pragma pack(N)
2、作用同上
#pragma pack(N)
待字节对齐的struct、union和class
#pragma pack()

看一个例子:

#pragma pack(push, 1)
struct S3 {
    char m1;      // 1-byte
    double m2;    // 8-byte
};
#pragma pack(pop)

这样就让这个结构体进行1字节对齐,即不进行对齐。此时结构体的大小就是9字节。

2.2 __attribute__关键字

  • __attribute__ ((packed)):取消在编译过程中的优化对齐,按照实际占用字节数进行对齐
  • __attribute((aligned (n))):让所作用的结构体成员对齐在n字节边界上。如果结构体中有成员变量的字节长度大于n,则按照最大成员变量的字节长度来对齐。
struct  person1{
	char *name;
	int  age;
	char score;
	int  id;
}__attribute__ ((packed));

struct  person2{
	char *name;
	int  age;
	char score;
	int  id;
}__attribute((aligned (n)));
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tilblackout

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值