有如下的两个结构体:
struct A struct B
{ {
int a; int a;
unsigned __int64 b; short c;
short c; unsigned __int64 b;
}; };
那么sizeof(A) 和sizeof(B)一样吗?让我在编译器里试一下,啊?怎么不一样?两个结构体明明相同,只是第二和第三个成员变量的位置颠倒了结果却大相径庭。到底是因为什么呢?
答案是编译器的数据对齐方式在作怪。以vc6.0为例,默认情况下的对其方式是8位。所以struct A的大小为24,struct B的大小为16,下面就具体分析一下数据空间占用情况。
在Struct A中的,编译器首先检测所有的成员变量中的size最大值。很显然unsigned __int64最大,sizeof(unsigned __int64)为8,然后第一个变量a为int型只占4个字节,但是为了对齐其被补上了四个字节,接着变量b在 变量a有效位置之后被放置,但是目前只有4个空闲的字节,根本放不下变量b,于是编译器就再申请了8字节的空间大小,将变量b放在4个空闲字节之后,也就是说变量b的起始位置在第九个字节。由于变量b需要8个字节所以没有留给变量c任何的剩余空间,于是变量c再次申请8个字节的空间用于存储自己,当然它本可以只申请2字节的空前就行了,但是为了对齐他只能申请8字节。那么最后我们就可以看到如下图所示的数据存储结构:
0 |
… |
… |
… |
8 |
… |
… |
… |
15 |
… |
… |
23 |
a |
… |
多申请的空间 |
b |
… |
… |
… |
c |
|
多申请的空间 |
在Struct B中的, 编译器前几步的处理也和struct A的一样,直到该处理变量c 时,编译器依然要先看看为变量a分配的空间是否还有多余并且多余的空间是否足以容纳下变量c,由于变量c只需要两个字节,而a却有4个字节的剩余空间,所以变量c就很轻松的被放置在a之后的4个字节内而不需要再申请空间。变量b依然申请8字节的空间并跟随在变量a空余空间之后。最后我们就可以看到如下图所示的数据存储结构:
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
… |
… |
… |
15 |
a |
|
|
|
c |
|
多申请的空间 |
b |
… |
… |
… |
|
通过以上的分析我们明白了结构体内部(也可以引伸到类的内部!)成员变量的声明顺序并不是随意的,尤其是在内存需求特别紧张的开发环境中。