在C中如下结构:
struct foo { char c1; short s; char c2; int i; };
假设结构成员在内存中紧凑排列,c1地址0,s地址应该是1,c2地址3,i地址4c1 00000000s 00000001c2 00000003i 00000004但VC6 中
#include<stdio.h>
Struct foo { char c1; short s; char c2; int i; };
int main()
{ struct foo a;
printf("c1\t%p\ns\t%p\nc2\t%p\ni\t%p\n", (unsigned int)(void*)&a.c1 - (unsigned int)(void*)&a, (unsigned int)(void*)&a.s - (unsigned int)(void*)&a, (unsigned int)(void*)&a.c2 - (unsigned int)(void*)&a, (unsigned int)(void*)&a.i - (unsigned int)(void*)&a);
printf("sizeof(foo)=%d\n",sizeof(foo)); return 0;
}
c1 00000000
s 00000002c2 00000004i 00000008这就是内存对齐而导致的问题
为什么会有内存对齐
以下内容节选自《Intel Architecture 32 Manual》。
字,双字,和四字在自然边界上不需要在内存中对齐。(对字,双字,和四字来说,自然边界分别是偶数地址,可以被4整除的地址,和可以被8整除的地址。) 无论如何,为了提高程序的性能,数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;然而,对齐的内存访问仅需要一次访问。 一个字或双字操作数跨越了4字节边界,或者一个四字操作数跨越了8字节边界,被认为是未对齐的,从而需要两次总线周期来访问内存。一个字起始地址是奇数但却没有跨越字边界被认为是对齐的,能够在一个总线周期中被访问。如果不在编码时指定内存对齐方式,由于不同平台有不同的默认对齐方式从而造成通讯时不同平台数据通信数据处理问题,需要注意