MENU

C++内存对齐

字节对齐:计算机中内存大小的基本单位是字节(byte),理论上讲,可以从任意地址访问某种基本数据类型,但实际的计算机系统对基本类型数据在内存中存放的位置有限制,即它的地址必须是2、4、8、16等倍数,则就要求各种数据类型按照一定的规则在空间上排序,这就是对齐。

对齐的规则

每个特定平台上的编译器都有自己的默认”对齐系数“。可以自行通过预编译命令设置#pragma pack(n),n可以取值1,2,4,8,16来改变这一系数。
有效对齐值:#pragma pack(n)指定值 和 结构体最长数据类型长度 最小的那个作为有效对齐值。

对齐规则:

  • 结构体变量的首地址是有效对齐值的整数倍
  • 结构体第一个成员的偏移量为0,以后每个成员相对于结构体首地址的 offset 都是该成员大小与有效对齐值中较小那个 即min(#pragma pack()指定的数,这个数据成员的自身长度)的整数倍,如有需要编译器会在成员之间加上填充字节
  • 结构体的总大小为有效对齐值的整数倍,如有需要,编译器会在最末一个成员之后加上填充字节

对齐的原因

  • 平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处去某些特定类型的数据
  • 性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。

样例

struct
{
    int i;    // 4个字节
    char c1;  // 1个字节
    char c2;  // 1个字节
}x1;
  • 对于x1,默认情况下(#pragma pack(8)),有效对齐值=min(#pragma pack()指定的数,这个数据成员的自身长度),即min(8,4)为4,sizeof后结果为8。
  • 对于x1,指定(#pragma pack(1)),有效对齐值=min(#pragma pack()指定的数,这个数据成员的自身长度),即min(1,4)为1,sizeof后结果为6。
  • 对于x1,指定(#pragma pack(2)),有效对齐值=min(#pragma pack()指定的数,这个数据成员的自身长度),即min(2,4)为2,sizeof后结果为6。
struct
{
    char c1;  // 1个字节
    int i;    // 4个字节
    char c2;  // 1个字节
}x2;
  • 对于x2,默认情况下(#pragma pack(8)),有效对齐值=min(#pragma pack()指定的数,这个数据成员的自身长度),即min(8,4)为4,sizeof后结果为12。
  • 对于x2,指定(#pragma pack(1)),有效对齐值=min(#pragma pack()指定的数,这个数据成员的自身长度),即min(1,4)为1,sizeof后结果为6。
  • 对于x2,指定(#pragma pack(2)),有效对齐值=min(#pragma pack()指定的数,这个数据成员的自身长度),即min(2,4)为2,sizeof后结果为8。
struct
{
    char c1;  // 1个字节
    char c2;  // 1个字节
    int i;    // 4个字节
}x3;
  • 对于x3,默认情况下(#pragma pack(8)),有效对齐值=min(#pragma pack()指定的数,这个数据成员的自身长度),即min(8,4)为4,sizeof后结果为8。
  • 对于x3,指定(#pragma pack(1)),有效对齐值=min(#pragma pack()指定的数,这个数据成员的自身长度),即min(1,4)为1,sizeof后结果为6。
  • 对于x3,指定(#pragma pack(2)),有效对齐值=min(#pragma pack()指定的数,这个数据成员的自身长度),即min(2,4)为2,sizeof后结果为6。
struct
{
    int a;      // 4个字节
    char b[6];  // 6个字节
    double c;   // 8个字节
}x4;
  • 对于x4,默认情况下(#pragma pack(8)),有效对齐值=min(#pragma pack()指定的数,这个数据成员的自身长度),即min(8,8)为8,sizeof后结果为24。
  • 对于x4,指定(#pragma pack(1)),有效对齐值=min(#pragma pack()指定的数,这个数据成员的自身长度),即min(1,8)为1,sizeof后结果为18。
  • 对于x4,指定(#pragma pack(2)),有效对齐值=min(#pragma pack()指定的数,这个数据成员的自身长度),即min(2,8)为2,sizeof后结果为18。

参考文章
C/C++内存对齐
内存字节对齐

标签: C++
返回文章列表 文章二维码 打赏
本页链接的二维码
打赏二维码