现在的位置: 首页 > 综合 > 正文

About Data Alignment(关于数据对齐)

2018年04月11日 ⁄ 综合 ⁄ 共 1318字 ⁄ 字号 评论关闭

 

原文:http://msdn.microsoft.com/zh-cn/library/ms253949.aspx

翻译:http://www.52rd.com/Blog/Detail_RD.Blog_imjacob_10489.html

      

       很多CPU,如基于Alpha, IA-64, MIPS, 和SuperH 体系的,拒绝读取未对齐数据。当一个程序要求其中之一的CPU读取未对齐数据时,这时CPU会进入异常处理状态并且通知程序不能继续执行。举个例子,在ARM, MIPS, 和SH硬件平台上,当操作系统被要求存取一个未对齐数据时默认通知应用程序一个异常。

       在不支持未对齐的内存访问的硬件平台上进行未对齐的内存访问会遭致巨大的性能损失。

 

对齐

 

       对齐是一种内存地址的特性,表现在内存地址对2的幂数取模上。例如,内存地址 0x0001103F模4结果为3;这个地址就叫做与4n+3对齐,4指出了所选用的2的幂的值。内存地址的对齐取决于所选择的关于2的幂值。(这个)相同的地址模8结果为7。

 

       一个内存地址符合表达式Xn+0 ,那么就说该地址对齐于X。

 

       CPU 执行指令就是对存储于内存上的数据进行操作,这些数据在内存上是以地址为标记的。对于地址来说,单独的数据会有其占用内存的字节数。如果它的地址对齐于它的字节数,那么就称作该数据自然对齐,否则称为未对齐。例如,一个标记8字节的浮点数据的地址对齐于8(即其地址满足8n+0),那么这个数据就自然对齐。

 

数据对齐的编译处理

 

       设备编译器以一种防止造成数据未对齐的方式来对数据进行地址分配。

 

       对于简单数据类型,编译器为其分配的地址是数据类型字节数的倍数。因此,编译器分配给long型变量的地址为4的倍数,就是说以2进制表示地址的话,最后两位为00。

       另外,编译器以一种自然对齐每个结构成员的方式来填充结构体。参看下面的代码里面的结构体struct x_。   

 struct x_
      {
        char a;     // 1 字节
         int b;      // 4 字节
         short c;    // 2 字节
         char d;     // 1 字节
       } MyStruct;

      编译器填充这个结构以使其自然对齐。

 

例如

 

      下面的代码说明了编译器是如何在内存中填充的。

//显示内存实际状态(布局)
struct x_
{
 char a;        // 1 字节
 char _pad0[3]; // 填充(3个字节)使b(下一个成员)在4字节的边界上
 int b;         // 4 字节
 short c;       // 2 字节
 char d;        // 1 字节
 char _pad1[1]; // 填充使X_的大小为4的整数倍
};

      两种定义在作sizeof(struct x_)运算都会返回12字节。

      第二种定义含有两种填充成分:

                ❉  char _pad0[3]使得int b 在“4-字节”边界上对齐

                ❉  char _pad1[1]使得结构数组struct _x  bar[3]的元素对齐。

      填充使得bar[3]各个元素能够自然对齐。

      下面的代码显示了bar[3]的内存结构:

      

抱歉!评论已关闭.