C语言的内存对齐

引言

 

先看下面这段程序

运行结果(输出)是:

sizeof(C):12

sizeof(D):8

2个结构体,成员个数,成员类型都一样,不同的只是成员的顺序,最终sizeof的结果却不相同。要解释这个问题就需要说明内存对齐。

 

为什么要对齐

 

为了能使CPU对变量进行高效快速的访问,变量的起始地址应该具有某些特性,即所谓的"对齐"。

 

基本概念

 

数据类型自身的对齐值: 一般地(32位机),对于char型数据,其自身对齐值为1,对于short型为2,对于int,float,double类型,其自身对齐值为4,单位字节。

结构体或者类的自身对齐值: 其成员中自身对齐值最大的那个值。

指定对齐值: #pragma pack (value)时的指定对齐值value。

数据成员、结构体和类的有效对齐值: 自身对齐值和指定对齐值中小的那个值。

因此,32位机中,#pragma pack(16)是没有意义的(long long的对齐值为8),原因是有效对齐值取自身对齐和指定对齐中小的那个值。

另外,不同的编译器有默认的指定对齐值(这也是为什么同一个结构在不同编译器中sizeof结果不同的原因),如VS系列默认对齐方式为#pragma pack(8),也就是说VS默认以8个字节对齐(如果结构体中某个成员的sizeof大于8)。VC6.0中可以这样修改默认的指定对齐方式:

[Project]|[Settings],c/c++选项卡Category的Code Generation选项的Struct Member Alignment中修改。

显然,编码时,可以通过#pragma动态地修改结构体的指定对齐值。

 

对齐原则

 

对齐方式影响结构体成员在结构体中的偏移,不妨设编译器指定对齐参数为n,对于结构体中的某一成员item,它相对于结构首地址的实际字节对齐数目X应该满足以下规则:

X = min ( n, sizeof(item) )

例如,对于结构体 struct A {char a; int b};

当位于32位系统,n=8时:

a的偏移为0,

b的偏移为4,中间填充了3个字节, b的X为4;

当位于32位系统,n=2时:

a的偏移为0,

b的偏移为2,中间填充了1个字节,b的X为2;

 

再如,对于结构体 struct B{int a;char b;char c;int d};

当位于32位系统,n=8时:

a 的偏移为0,

b的偏移为4,

c的偏移为5,

d的偏移为8,中间填充了2个字节

当位于32位系统,n=2时:

a 的偏移为0,

b的偏移为4,

c的偏移为5,

d的偏移为6

 

最后,结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章