关键字:
C
+
+,
数据对齐
摘要:
数据对齐对内存的占用影响很大,良好的变量声明顺序有利于减少资源的占用和提高运行效率。
正文:
有如下的两个结构体:
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
|
…
|
…
|
…
|
|
通过以上的分析我们明白了结构体内部
(
也可以引伸到类的内部!
)
成员变量的声明顺序并不是随意的,尤其是在内存需求特别紧张的开发环境中。