字节对齐

    技术2024-11-18  58

    在codeWarrior编译的程序 和 win7下vs10编译的程序 利用24L01无线模块进行通讯时.除了学到了 二者程序存储的机器字节顺序不同,在使用如short这样的大于1字节的变量类型 需要进行字节的逆序 以外 ,在编写协议的时候想用结构体简化程序,减少使用memcpy, 但我知道结构体在编译的时候编译器一般存在一些“字节对齐”规则(包括了align of member  和 structure alignment) ,之前只是很马虎的了解了一下,今天又认真了解了“字节对齐”.

     

    为了简化叙述,这里用 [n 这个符号代表一个成员变量 相对于他所在的结构体的首地址的offset字节数.

     

    (1) align of member 

    align of member 其实也就是在决定每个成员变量的 [n 

    而它完全由 该成员变量的对齐值决定.

    而某一个成员变量的对齐值 = min( pack setting value, sizeof(该成员变量) )

    对于vs10,可以用#pragma pack(show) 宏命令显示 pack setting value 的值(在vs上一般是8)

    (在codeWarrior 5.9.0里#pragma pack 语句编译时会被显示警告,意思是没有理会该宏,所以对于codeWarrior 对“字节对齐”的规定是否遵循一般的规则 也很难得知,自己也只能靠实践去找出)

    对齐值怎么决定每个成员变量的 [n 呢?

    对于vs10,编译器按照

    " 一个成员变量的 [n 必须为 该员变量的对齐值 的 整数倍"

    这一规则去决定的.

     

    看一个例子:(程序中#pragma pack(8)是为了保证pack setting value = 8 ,不过vs10默认就是8, 最后#pragma pack()是为了还原上一次pack setting value)

     

    #pragma pack(8) struct S { char a;//[0 short b;//[2 char c;//[4 int f ;//[8 char e ;//[12 }; #pragma pack()

    编译以后,

    对于 a的对齐值  = min(8,1) = 1 ; 编译器会选择把a放在[0 处满足      0%1 == 0  

    对于 b的对齐值  = min(8,2) = 2; 编译器会选择把b放在 [2 处才满足   2%2 == 0   (这就和a隔了一个字节)

    对于 c的对齐值  = min(8,1) = 1 ; 编译器会选择把c放在 [4 处满足      4%1 == 0   (紧挨着b)

    对于 f的对齐值  = min(8,4) = 4; 编译器会选择把f放在   [8 处才满足   8%4 == 0   (这就和c 隔了3个字节)

    对于 e的对齐值  = min(8,1) = 1 ; 编译器会选择把e放在 [12 处满足    12%1 == 0   (紧挨着f)

     

    所以仅就这些成员变量所占的空间来算 以上成员占用13字节 ,但是sizeof(S) 却= 16

    这就需要下一条规则来解释:

     

    (2)structure alignment

    对于structure的长度有一条规定:

    "结构体的长度 应该是 max( max(结构体各成员的对齐值) ,align(#)设置的值 )  的整数倍"

    其中,align(#)设置的值是指 指令: __declspec(align(n )) 当中的n, n的取值为2的1次方至2的8192次方.

    大多数情况不用考虑这条指令,对于上面的代码,它用起来看起来会是这个样子:

    __declspec( align(32) )struct S { char a;//[0 short b;//[2 char c;//[4 int f ;//[8 //char e; }; 

    我也没用过, 更多详情可以再去搜索.

     

    当然,第一段代码并没有使用这个奇怪的指令,所以max( max(结构体各成员的对齐值) ,align(#)设置的值 )  就是 max(结构体各成员的对齐值) ,容易看出,第一段代码中,int  f ;的对齐值最大 = 4.

     

    所以 ,编译器要使结构体S 占用4的整数倍的字节. 这就可以解释 sizeof(S) = 16 而非 13字节.

     

    对于这篇文章,我主要参考学习了这个地址:

    http://www.cnblogs.com/flying_bat/archive/2008/04/23/1167611.html

     

    by ga6840

    最新回复(0)