子节对齐

来源:互联网 发布:淘宝联盟如何一店多购 编辑:程序博客网 时间:2024/06/13 02:55

什么是子节对齐

考虑下面这样一个结构体定义:
struct _student{
   char sex;
   int length;
   char name[10];
  };
  struct _student student;
由于在x86下,GCC默认按4字节对齐,它会在sex后面填充3个子节,在name后面填充2个子节,以使得length在内存的4子节整数倍边界上,同时也使得整个结构体对齐。于是我们sizeof(student)会得到长度为20,而不是15。

为什么要子节对齐

需要字节对齐的根本原因在于CPU访问数据的效率问题。假设上面整型变量的地址不是自然对齐,比如为0x00000002,则CPU如果取它的值的话需要访问两次内存,第一次取从0x00000002-0x00000003的一个short,第二次取从0x00000004-0x00000005的一个short然后组合得到所要的数据,如果变量在0x00000003地址上的话则要访问三次内存,第一次为char,第二次为short,第三次为char,然后组合得到整型数据。而如果变量在自然对齐位置上,则只要一次就可以取出数据。一些系统对对齐要求非常严格,比如sparc系统,如果取未对齐的数据会发生错误。

什么时候要设置子节对齐

在设计不同CPU下的通信协议时,或者编写硬件驱动程序时寄存器的结构,这两种场景都需要按一字节对齐。即使看起来本来就自然对齐的也要使其对齐,以免不同的编译器生成的代码不一样。

子节对齐的原则

对于标准数据类型,它的地址只要是它的长度的整数倍就行了,而非标准数据类型按下面的原则对齐:

  • 数组 :按照基本数据类型对齐,第一个对齐了后面的自然也就对齐了。
  • 联合 :按其包含的长度最大的数据类型对齐。
  • 结构体: 结构体中每个数据类型都要对齐。

更改编译器的缺省字节对齐方式

在vc中默认是4字节对齐的,GNU gcc 也是默认4字节对齐。可以通过下面的方法来改变缺省的对齐设置:
· 使用伪指令#pragma pack (n),C编译器将按照n个字节对齐。
· 使用伪指令#pragma pack (),取消自定义字节对齐方式。
另外,还有如下的一种方式:
· __attribute((aligned (n))),让所作用的结构成员对齐在n字节自然边界上。如果结构中有成员的长度大于n,则按照最大成员的长度来对齐。
· attribute ((packed)),取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐。

原创粉丝点击