数据地址对齐

来源:互联网 发布:免费云数据库 编辑:程序博客网 时间:2024/05/21 19:30

数据地址对齐是从C语言映射到机器语言时,C语言隐含做的事情。这一点值得理解。

我们先看看数据:

C声明 Intel数据类型 汇编代码后缀 x86-64大小(字节) IA32大小 char 字节 b 1 1 short 字 w 2 2 int 双字 l 4 4 long int 四字 q 8 4 long long int 四字 q 8 8 char * 四字 q 8 4 float 单精度 s 4 4 double 双精度 d 8 8 long double 扩展精度 t 10/16 10/12

图3-34 x86-64的标准数据类型大小(与IA32比较,长整数和指针需要8个字节,而IA32只需要4个字节)

计算机系统对基本数据类型合法地址做出了一些限制,要求某种类型对象的地址必须是某个值K(通常是2/4/8)的倍数。这种对齐限制简化了形成处理器和存储器系统之间的接口设计。

无论是否对齐,IA32硬件都能正常的工作,但是Intel建议对齐来提高存储系统的性能。Linux对齐策略是2字节数据类型的地址必须是2的倍数,而较大的数据类型的地址必须是4的倍数。实现多媒体操作的SSE指令要求强制对齐,任何试图以不满足对齐要求的地址来访问存储器都会导致异常,默认的行为是程序终止。Windows的对齐策略更加严格——任何K字节基本对象的地址必须是K的倍数。Linux的惯例是8字节数据在4字节边界上对齐,这可能对i386很好,因为过去存储器十分缺乏,而存储器接口只有4字节宽。对于现代存储器而言,Windows对齐策略更好。在Windows和Linux 上数据类型long double(拓展精度)都有4字节对齐的要求,为此GCC产生的IA32代码分配12个字节(虽然实际的数据类型只需要10个字节)。

x86-64遵循一组更严格的对齐策略。对于任何需要K字节的标量数据类型来说,它的起始地址必须是K的倍数,因此数据类型long和double以及指针,都必须在8字节边界上对齐,此外数据类型long double使用16字节对齐。强加这些对齐条件是为了提高存储器性能——最新的处理器中,存储器接口被设计成读或者写对齐的块,这些块是8或者16字节。

针对更加严格的对齐策略,下面举例说明。

例3.53 对于下列结构声明,确定每个字段的偏移量,结构的整个大小,以及在x86-64下它的对齐要求。

A. struct P1 {int i; char c; long j; char d; };

答案:
偏移量: i:0, c:4, j:8, d:16
整个大小:24
对齐要求:8对齐

B. struct P2 {long i; char c; char d; int j; };

答案:
偏移量:i:0, c:8, d:9, j:12
整个大小:16
对齐要求:8对齐

C. struct P3 {short w[3]; char c[3] };

答案:
偏移量:w:0, c:6
整个大小:10
对齐要求:2

D. struct P4 {short w[3]; char *c[3] };

答案:
偏移量:w:0, c:8
整个大小:32
对齐要求:8

E. struct P3 {struct P1 a[2]; struct P2 *p};

答案:
偏移量:a:0, b:48
整个大小:56
对齐要求:8

总的来说:
x86-64和IA32中的数据结构遵循相同的原则:数组是作为同样大小的块的序列来分配的,这些块中保存着数组元素。结构是作为变长的块的序列来分配的(要确保每个元素满足对齐要求,以及整体可能作为数组元素的对齐要求,因此在元素之间以及元素末尾可能有空隙),块中保存着结构元素。联合是作为一个单独的块来分配的,这个块足够大,能够装下联合中最大的元素。

0 0
原创粉丝点击