字节对齐
|
为了能使CPU对变量进行高效快速的访问,变量的起始地址应该具有某些特性,
即所谓的“对齐”。例如对于4字节的int类型变量,其起始地址应位于4字节边界上, 即起始地址能够被4整除。变量的对齐规则如下(32位系统):
Type
Alignment
char
在字节边界上对齐
short (16-bit)
在双字节边界上对齐
int and long (32-bit)
在4字节边界上对齐
float
在4字节边界上对齐
double 在8字节边界上对齐 structures X = min(n, sizeof(item)) 由N和该成员字节数中,较小的一个决定 例如,对于结构体 struct {char a; int b} T; 当位于32位系统,n=8时: 当位于32位系统,n=2时: 结构体的sizeof N由编译参数决定。#paragma pack(N) 结构体的末尾填充,由N和最大成员字节数中,较小的一个决定 例如:32位系统,n=8,
注意:
1) 对于空结构体,sizeof == 1;因为必须保证结构体的每一个实例在内存中都
有独一无二的地址。
2) 结构体的静态成员不对结构体的大小产生影响,因为静态变量的存储位置与
结构体的实例地址无关。
例如:
struct {static int I;} T; struct {char a; static int I;} T1;
sizeof(T) == 1; sizeof(T1) == 1;
3) 某些编译器支持扩展指令设置变量或结构的对齐方式,如VC, 详见MSDN(alignment of structures) 并不是要求#pragma pack(8),就一定是每个成员都是8字节对齐 struct s2 |
1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
字,双字,和四字在自然边界上不需要在内存中对齐。(对字,双字,和四字来说,自然边界分别是偶数地址,可以被4整除的地址,和可以被8整除的地址。)
无论如何,为了提高程序的性能,数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;然而,对齐的内存访问仅需要一次访问。
一个字或双字操作数跨越了4字节边界,或者一个四字操作数跨越了8字节边界,被认为是未对齐的,从而需要两次总线周期来访问内存。一个字起始地址是奇数但却没有跨越字边界被认为是对齐的,能够在一个总线周期中被访问。
某些操作双四字的指令需要内存操作数在自然边界上对齐。如果操作数没有对齐,这些指令将会产生一个通用保护异常(#GP)。双四字的自然边界是能够被16整除的地址。其他的操作双四字的指令允许未对齐的访问(不会产生通用保护异常),然而,需要额外的内存总线周期来访问内存中未对齐的数据。