#pragma pack的使用

好久没写博客了,还是打算恢复起来,记录所学内容是个好习惯,应该保持!

#pragma pack的作用
程序编译器对变量的存储带有一定随机性,而pragma pack是一种字节对齐方法,采用人为设定的方式将存储数据按一定格式排布。 百科中提到了其一种作用:有的平台每次读都是从偶地址开始,如果一个int型存放在偶地址开始处,一个读周期就可以读出,如果存在奇地址开始处,则需要两个周期,并且需要对读出结果高低字节进行拼凑,降低了读取效率。因此对于这种平台人为对齐数据在偶地址开头处是有必要的。因为刚接触,我目前感觉其最大作用就是数据整齐排布后它们的 地址排布也十分清晰(尤其是较为复杂固定数据结构),知道一个数据的地址可以推算出其他数据地址,不用再每次都去取地址。

#pragma pack的使用方法
百科里写的比较复杂,其实一般用起来也就设置一个对齐长度就行了,即:
#pragma pack(n) //开始对齐,n是对齐长度
{
   此部分定义的数据进行对齐
}
#pragma pack ()  //取消对齐
#pragma pack对齐数据结构大小的计算方法
网上有的写的比较复杂,我就总结一下:
(1)首先,实际对齐长度不一定是你设置的对齐长度,应该是 实际对齐长度=min(设置对齐长度,数据的最长长度)。什么意思,举个例子,你设置对齐长度为4,你的数据中包括int型(长度4),那对齐长度就是4;如果你的数据中仅有short(长度2),那么对齐长度就是2,为什么是这样可以仔细琢磨一下。
(2)保证每一个数据满足:  不同类型数据都满足:  首地址%数据长度 = 0 
(3)补齐末尾的空间,保证长度对齐,即 总长度%实际对齐长度=0

以上有点抽象,举几个例子:
#pragma pack(4)
struct test1
{
   int a;   
   char b;  
   short c;
   char d;
};

#pragma pack ()
(1)数据中最长为int(长度4),设置对齐长度4,因此实际对齐长度4
(2)int首地址0,长度4,0%4=0,没问题,占据[0,3];char首地址4,长度1,4%1=0没问题,占据[4];short首地址5,长度2,5%2!=0,因此不行,此处要补空位,short首地址为6,6%2=0,没问题了,占据[6,7];char首地址8,长度1,8%1=0没问题,占据[8]。
(3)最后补齐,[9,10,11],使得12%4=0。
因此 sizeof(test1) =12。
#pragma pack(2)
struct test2
{
   int a;   
   char b;  
   short c;
   char d;
};

#pragma pack ()

这个例子与上一个类似,值得注意的是设置对齐长度为2。按照取最小原则,实际对齐长度为2,因此第三步中10%2=0,即sizeof(test2)=10。

#pragma pack(4)
struct test3
{
   char b;  
   short c;
   char d;
};

#pragma pack ()
在这个例子中,去掉了整形int,因此数据中最大长度为2(short),即使设置了对齐长度为4,实际对齐长度仍为2。通过以上步骤可以得到sizeof(test3)=6。


参考资料:
百度百科:#pragma pack:https://baike.baidu.com/item/%23pragma%20pack/3338249
stm32中使用 #pragma pack:https://www.cnblogs.com/King-Gentleman/p/5297355.html

猜你喜欢

转载自blog.csdn.net/mingtian715/article/details/80033769