正文

结构体的成员变量的对齐问题2006-04-06 17:08:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/clever101/12008.html

分享到:

结构体的大小是一个令人迷惑不解的问题,不信,我出一题让你算算看:

 

enum DataType{IntData,CharData,VcharData};

 

struct Item   

 

{

 

     char ItemNAme[30];

 

       DataType ItemType;

 

       char ItemDecr[50];

 

       int  ItemLength;

 

};

 

在你使用sizeof之前你能知道它的大小吗?我想即使你用sizeof得出结果后,结果还是会让你大吃一惊的:怎么是这个?

 

 

 

一.为什么要对齐?

 

Windows核心编程》里这样说:当CPU访问正确对齐的数据时,它的运行效率最高,当数据大小的数据模数的内存地址是0时,数据是对齐的。例如:WORD值应该是总是从被2除尽的地址开始,而DWORD值应该总是从被4除尽的地址开始,数据对齐不是内存结构的一部分,而是CPU结构的一部分。当CPU试图读取的数值没有正确的对齐时,CPU可以执行两种操作之一:产生一个异常条件;执行多次对齐的内存访问,以便读取完整的未对齐数据,若多次执行内存访问,应用程序的运行速度就会慢。在最好的情况下,是两倍的时间,有时更长。

 

 

 

二.成员变量对齐的原理

 

我花了一个上午,看了一些资料,总算把这个问题搞明白了。下面我以一些例子说明结构体成员变量的对齐问题。

 

对于

struct s1

{

 

char a;

 

long int d;

double c;

};

 

这个结构体的大小是16。编译器默认的一般是8字节对齐。a的大小是1,它就按1字节对齐(因为比指定的8小),存诸在0偏移的地方;b大小为4,它就按4字节对齐(因为比指定的8小),存在偏移4——7的位置,c大小为8,存在8——15的位置。这样3个成员共占用了16个字节。由于该结构最大成员c大小为8,所以结构按8字节对齐,168园整还是16,因此sizeof s1 = 16.

 

而对于

 

struct s2

 

{

 

char a;

 

long int d;

 

 

 

double c;

 

char e;

 

};

 

这个结构体的大小是24。前3个成员和上面一样存诸,d4——7位置,c8——15位置,但e1字节对齐,存在偏移位置16,这样4个成员占用了17个字节。由于该结构的最大的数据成员c的大小是8个字节,所以178园整得24

 

 

 

当然你可以使用#pragma指令指定编译器按4字节对齐。即

 

#pragma pack(4)      // 这里也可以是#pragma pack(push,4)

 

 

 

struct s1

 

{

 

char a;

 

long int d;

 

double c;

 

};

 

 

 

struct s2

 

{

 

char a;

 

long int d;

 

double c;

 

char e;

 

};

 

 

 

这时s1的大小还是16,而s2的大小变为20。我们来分析一下,对s1来说,按4字节对齐和按8字节对齐个数据成员的存诸位置是一样的,只不过是最后一部园整时,164园整还是16。对s2就不一样了,a的大小为1(比指定的4字节对齐要小),按1字节对齐,存诸在0位置,d的大小是4(大于等于指定的4字节),按4字节对齐,存诸在4——7位置,c的大小是8(大于指定的4字节),按4字节对齐,这样存诸在8——15e的大小是1,存储在位置16,这样整个结构体的长度是17174园整,得20。你也看到并不是指定编译器按4字节对齐就按4字节对齐的。比如下面的结构体:

 

#pragma pack(4)

 

struct TestStruct2

 

{

 

   char m1[11];

 

   short m2;

 

};

 

  你知道它的大小吗?是14。因为m11字节对齐,存诸在0——11位置,m22字节对齐,存诸在12——13位置。结构体占用13个字节,因为结构体内最大的成员的数据类型是short,大小为2,比指定的对齐字节4小,所以132园整,得14。综的说来就是结构体成员的对齐是用成员本身的大小和#pragma pack(push,n)中的n中较小的数对齐,例如如果成员大小为2,而你指定的对齐方式是4,则该成员按2对齐;结构本身的对其是用结构中最大成员的大小和#pragma pack(push,n)中的n较小的数对齐,即最后的园整,例如如果结构中最大成员大小8,而你指定对齐是16,则结构本身按8对齐。

 

 

 

开头题目的大小是92。你算到了吗?下面这个结构体的大小又是多少呢?

 

enum DataType{IntData,CharData,VcharData};

 

#pragma pack(2)

 

struct Item   

 

{

 

       char ItemNAme[30];

 

   DataType ItemType;

 

   char ItemDecr[50];

 

   int  ItemLength;

 

};

 

阅读(5132) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册