c++字节对齐问题

为什么需要字节对齐

  • 某些平台只能在特定的地址处访问特定的类型的数据。
  • 提高存取数据的速度

对齐的准则

  • 数据类型自身对齐值: char为1字节,short为2字节,long/int/float为4字节,double/long long为8字节。
  • 结构体或类自身对齐值:它最后的对齐值为其成员变量中自身对齐值中最大的那个值的整数倍。
  • 指定对齐值:#pragma pack (value)时的指定对齐值value
  • 数据成员、结构体和类的有效对齐值:自身对齐值和指定对齐值中较小者,即有效对齐值=min{自身对齐值,当前指定的pack值}

位域对齐方式

  • 如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的字段将紧邻前一个字段存储,直到不能容纳为止;
  • 如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字段将从新的存储单元开始,其偏移量为其类型大小的整数倍;
  • 如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,VC6采取不压缩方式,Dev-C++和GCC采取压缩方式;
  • 如果位域字段之间穿插着非位域字段,则不进行压缩
  • 整个结构体的总大小为最宽基本类型成员大小的整数倍,而位域则按照其最宽类型字节数对齐。

例如:

1
2
3
4
5
6
7
8
struct StructBitField{
int element1 : 1;
int element2 : 5;
int element3 : 29;
int element4 : 6;
char element5 :2;
char stelement; //在含位域的结构或联合中也可同时说明普通成员
};

结构体中最宽类型int为4字节,因此结构体按照4字节对齐。所以在vc6中,其sizeof为16.

笔试题

1
2
3
4
5
6
7
8
struct s
{
int x: 3;
int y: 4;
int z: 5;
double a;
};
求sizeof(s)

分析:
首先结构体中最宽的是8字节的double,所以结构体按照8字节对齐。而我们发现x,y,z属于int型的位域,而且三个位域所占的位数为12位,未超过一个int型所占的32位,因此只需要4个字节就可以表示xyz。另外,由于double自身的对齐方式为:8字节,所以最终sizeof(s) = 16.