有关结构体对齐

对齐的作用和原因:各个硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型的数据只能从某些特定地址开始存取。比如有些架构的CPU在访问 一个没有进行对齐的变量的时候会发生错误,那么在这种架构下编程必须保证字节对齐.其他平台可能没有这种情况,但是最常见的是如果不按照适合其平台要求对 数据存放进行对齐,会在存取效率上带来损失。比如有些平台每次读都是从偶地址开始,如果一个int型(假设为32位系统)如果存放在偶地址开始的地方,那 么一个读周期就可以读出这32bit,而如果存放在奇地址开始的地方,就需要2个读周期,并对两次读出的结果的高低字节进行拼凑才能得到该32bit数 据。显然在读取效率上下降很多。

 

 1 自然对界

各个成员按照它们被声明的顺序在内存中顺序存储,第一个成员的地址和整个结构的地址相同。自然对界(natural alignment)即默认对齐方式,是指按结构体的成员中size 最大的成员对齐。
例如:
struct naturalalign
{
char a;
short b;
char c;
};
在上述结构体中,size 最大的是short,其长度为2 字节,因而结构体中的char 成员a、c 都以2 为单位对齐,
sizeof(naturalalign)的结果等于6;
如果改为:
struct naturalalign
{
char a;
int b;
char c;
};
其结果显然为12。

 

2 指定对界

一般地,可以通过下面的方法来改变缺省的对界条件:
· 使用伪指令#pragma pack (n),编译器将按照n 个字节对齐;
· 使用伪指令#pragma pack (),取消自定义字节对齐方式。
注意:如果#pragma pack (n)中指定的n 大于结构体中最大成员的size,则其不起作用,结构体
仍然按照size 最大的成员进行对界。
例如:
#pragma pack (n)
struct naturalalign
{
char a;
int b;
char c;
};
#pragma pack ()
当n 为4、8、16 时,其对齐方式均一样,sizeof(naturalalign)的结果都等于12。而当n 为2
时,其发挥了作用,使得sizeof(naturalalign)的结果为6。

3 实际对齐方式:

Actual Align = min ( Order Align, Natual Align )

  对于复杂数据类型(比如结构等):实际对齐方式是其成员最大的实际对齐方式:

Actual Align = max( Actual align1,2,3,…)


4 几个例子:

struct A
{
    int a;
    char b;
    short c;
}; //size = 8
struct B
{
    char b;
    int a;
    short c;
};//size = 12

#pragma pack (2) /*指定按2字节对齐*/
struct C
{
    char b;
    int a;
    short c;
}; //size = 8

#pragma pack () /*取消指定对齐,恢复缺省对齐*/

 

#pragma pack(8)
struct example1
{
short a;
long b;
};//size = 8  指定对齐大于自然对齐,无效
struct example2
{
char c;
example1 struct1;
short e;
}; //size = 16 实际对齐方式按最大成员(example1)为4
#pragma pack()

 

#pragma pack(8) //指定Align为 8
struct STest1
{
    char ch1;
    long lo1;
    char ch2;
} // size = 12 指定对齐大于自然对齐,无效
#pragma pack()

  struct STest2
  {
      char ch3;
      STest1 test;
  }// size = 16 按STest1对齐
#pragma pack(2) //指定Align为 2
  struct STest3
  {
      char ch3;
      STest1 test;
  }// size = 14
#pragma pack()

5 注意事项:

 

  1、 这样一来,编译器无法为特定平台做优化 ,如果效率非常重要,就尽量不要使用#pragma pack, 尽量用好的定义来压缩空间,把结构中的变量按照 类型从小到大声明,尽量减少中间的填补空间 如果必须使用,也最好仅在需要的地方进行设置。

  2、需要加 pack 的地方一定要在定义结构的头文件中加,不要依赖命令行选项,因为如果很多人使用该头文件,并不是每个人都知道应该 pack 这特别表现在为别人开发库文件时,如果一个库函数使用了struct作为其参数,当调用者与库文件开发者使用不同的 pack 时,就会造成错误,而且该类错误很不好查。

  3、 在VC及BC提供的头文件中,除了能正好对齐在四字节上的结构外,都加了 pack ,否则 我们编的Windows程序哪一个也不会正常运行。

  4、 在 # pragma pack (n) 后一定不要include其他头文 件,若包含的头文件中改变了align值,将产生非预期结果。

  5、 不要多人同时定义一个数据结构。这样可以保证一致的 pack 值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值