今天咱们就闲话少说直接进入正题了,(旁边来一人:靠!你不进入正题还想怎么样啊?你小子是不是找抽?)晕!这么想知道答案!别打偶,偶讲就是了......................................
让偶们先来看下面这个结构体:
struct stu1
{
int a;
char b;
};
来看看sizeof(stu)的结果为多少? (小A: 不就是5么~你小子还卖什么关子.......)
看结果是什么?没想到吧?呵呵!(得意洋洋!!)
(一屠夫上台: 怎么是8啊?你小子拿什么破编译器糊弄人)晕!屠夫也知道编译器??/
你先别急,再来看下一个例子:(急也没用!)
struct stu2
{
char b;
int a;
}
这个sizeof(stu2)是多少?
(屠夫又来了:怎么还是8啊?)呵呵!拨开迷雾见晴天,想要知庐山真面目.现在DEGUG工具派上用场了。(小A:得八哥是什么东西?)
得八哥~~~~~~~DEGUG就是调试工具,它可以看看我的程序(欠扁啊?是我们的程序)在内存到底是怎么样的。
好了,现在创建一个结构体变量stu2 s2 {" a ", 0x12345678h}; stu1 s1 {0x12345678, " a "}
运行DEGUG,怎么样发现了什么?
在第一个结构体中char b的后面内存有三个字节是添了数据的.也就是这样 78 56 34 12 61 cc cc cc
而在第二个结构体中CHAR B的后面内存中也添加了数据.61 cc cc cc 78 56 34 12
这又是怎么回事呢?(问谁呢?你是干什么的?)
需要字节对齐当然有设计者的考虑了,原来这样有助于加快计算机的存取速度,否则就得多花指令周期了。所以,编译器通常都会对结构体进行处理,让宽度为2的基本数据类型(short等)
都位于能被2整除的地址上,让宽度为4的基本数据类型(int等)都位于能被4整除的地址上。正是因为如此两个数中间就可能需要加入填充字节,所以结构体占的内存空间就增长了。
其实字节对齐的细节和具体编译器实现相关,但一般而言,满足三个准则:
1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
2) 结构体每个成员相对于结构体首地址的偏移量都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节;例如上面第二个结构体变量的地址空间。
3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节。例如上面第一个结构体变量。(哎呀!知道!真实多嘴!)
现在就可以解释上面的问题了,第一个结构体变量中成员变量最宽为4(SIZEOF(INT) = 4),所以S1变量首地址必须能被4整除。(不信你试试!)S1的大小也应该为4的整数倍。但是现在s1中
有 4 + 1 的空间,所以为了满足第三个条件就在char b的后面在加上三个字节的空间以凑够8个字节空间。第二个结构体变量S2中 成员变量最大宽度为4,而且按照以前的理解int a 的地址
和s2的地址相差5个字节,但是为了满足第而个条件(相差的距离------偏移地址必须是4的整数倍)所以在char b的后面添加了三个字节的空间以保证int a的偏移地址是4的整数倍即为4。
至于涉及到结构体嵌套的问题,你也可以用上述方法总结的,只不过你把被嵌套的结构体在原地展开就行了,不过在计算偏移地址的时候被嵌套的结构体是不能原地展开的必须当作整体。
嘿嘿!偶申明一点,上述三条建议不是偶说的,是做编译器的工程师总结出来的,偶只是借用而已。
呵呵!希望各给都明白了!
HAVE FUN!