数据地址对齐

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

我们先看看数据:

C声明Intel数据类型汇编代码后缀x86-64大小(字节)IA32大小
char字节b11
shortw22
int双字l44
long int四字q84
long long int四字q88
char *四字q84
float单精度s44
double双精度d88
long double扩展精度t10/1610/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中的数据结构遵循相同的原则:数组是作为同样大小的块的序列来分配的,这些块中保存着数组元素。结构是作为变长的块的序列来分配的(要确保每个元素满足对齐要求,以及整体可能作为数组元素的对齐要求,因此在元素之间以及元素末尾可能有空隙),块中保存着结构元素。联合是作为一个单独的块来分配的,这个块足够大,能够装下联合中最大的元素。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值