正文
typedef struct _tag_Test1
{
uint8_t member1;
uint16_t member2;
}sTest1;
stSize = sizeof(sTest1);
1
#pragma pack
#pragma pack 是一个编译指令,用于指定结构体、联合体和类成员的字节对齐方式。在 Keil uVision5 中,可以使用 #pragma pack 指令来设置字节对齐方式。一般我们用如下方式标识#pragma pack(n)
其中,n 是对齐系数,表示按照 n 字节对齐。常见的对齐系数包括 1、2、4、8 等。例如,若要将对齐系数设置为 4,比如:#pragma pack(4),该指令通常放置在结构体、联合体或类的定义之前,以影响其后的所有定义,这里尤其需要注意,很多时候忘记恢复字节对齐导致了一些没必要的问题。这样一来,所有在 #pragma pack 后声明的结构体、联合体或类成员都将按照指定的字节对齐方式进行排列。
那么如果我们需要取消则需要采用#pragma pack () 来取消结构体对齐。
#pragma pack (1)
typedef struct _tag_Test2
{
uint8_t member1;
uint16_t member2;
}sTest2;
#pragma pack () // 取消结构体对齐
stSize = sizeof(sTest2);
通过这样的定义,使得sTest2结构体整体大小只占用3个字节在,这种方式在MDK中比较常用。
当然有经验的朋友该说了,我用#pragma pack(push,n)比较多,没错,该语法也同样是可以的,比如例子:
//#pragma pack (1)
#pragma pack(push,1)
typedef struct _tag_Test2
{
uint8_t member1;
uint16_t member2;
}sTest2;
//#pragma pack () // 取消结构体对齐
#pragma pack(pop)
stSize = sizeof(sTest2);
既然都聊到这个份上了,该谈谈他们的差异了:
#pragma pack(n) 和 #pragma pack(push, n) 其实在功能上没太大的区别,仅仅只是在使用方面略有不同。
#pragma pack(n):
这个指令直接设置当前字节对齐系数为 n。这意味着在此指令之后声明的结构体、联合体或类成员都将按照指定的字节对齐方式进行排列。
每次使用 #pragma pack(n) 时,都会覆盖之前的对齐设置,因此它可能会影响后续的代码。
没有保存当前的对齐方式,因此在使用完之后,如果需要还原到先前的对齐方式,就需要手动重新设置。
#pragma pack(push, n):
这个指令其实也是设置当前字节对齐系数为 n。但是它还有一个功能,就是将当前的对齐方式保存到编译器的栈中。
这意味着,使用 #pragma pack(push, n) 后,可以在代码的后续部分使用 #pragma pack(pop) 来恢复之前保存的对齐方式,而不会受到之后代码中 #pragma pack 指令的影响。
因此,#pragma pack(push, n) 更灵活,可以避免在代码的后续部分不小心修改了对齐方式而导致错误。
2
__attribute__((__packed__))
__attribute__((__packed__)) 是 GCC 和一些兼容 GCC 的编译器(如 Clang)提供的一个特性,用于指示编译器以紧凑的方式存储结构体或类,即取消对齐。
使用案例如下:
typedef struct __attribute__ ((__packed__)) _tag_Test3
{
uint8_t member1;
uint16_t member2;
}sTest3;
stSize = sizeof(sTest3);
那么最终结构体的大小也将是3个字节。
3
干脆的__packed
相信有经验的各位都比较喜欢使用这个属性吧:
typedef __packed struct _tag_Test4
{
uint8_t member1;
uint16_t member2;
}sTest4; ;
stSize = sizeof(sTest4);
__packed 是一种特性,指示编译器取消对其成员的自然对齐。它的作用类似于 __attribute__((__packed__)),但是它更加与平台无关,因为它是一种更通用的约定,不依赖于特定编译器。
虽然说__packed 是一种常见的约定,但它并非标准 C 语言的一部分,因此在不同的编译器和平台上可能具有不同的行为,使用时应谨慎考虑平台兼容性和性能问题。
最后
好了,今天就跟大家分享这么多了,如果你觉得有所收获,一定记得点个赞~
bug菌唯一、永久、免费分享嵌入式技术知识平台~
推荐专辑 点击蓝色字体即可跳转
☞ MCU进阶专辑
☞ 专辑|手撕C语言
☞ 专辑|经验分享