【Struct(结构体)杂谈之四】以空间换时间,Struct(结构体)中的成员对齐之道(上)
请先看一道面试题:
问题: 阅读下面一段代码并回答题目之后的问题:
下面,我们把代码修改一下:
咦?结构体的大小不是将结构体元素单纯相加就可以的吗?怎么结果却变成8了呢?
要回答这个问题,需要从计算机的地址对齐讲起。至于为什么需要对齐,当然是对齐能够带来很多好处的。
第一,可以大大简化处理器和存储器之间接口的硬件设计;第二,提高处理器访问数据的效率。
首先讲下,对齐(alignment)就是计算机系统对基本数据类型的可允许地址做了限制,某种类型的对象的地址必须是某个值k的倍数。
以IA32为例,在自然对齐方式下,基本数据类型(如short,int,double)变量的地址必须被他们的大小整除。通俗的说,对于int类型的变量,因为宽度为4,因此存放int类型变量的起始地址必须能被4整除,宽度为2的基本数据类型(short等)则位于能被2整除的地址上,以此类推对于char和bool类型的变量,由于其只占用一个字节,则没有特别要求。
我们修改下程序,让其输出成员变量的地址:
从上述结果中,可以看出在struct ALIGN1中,int mA的起始地址为0x0012ff4c可以被4整除,short mB的起始地址为0x0012ff50可以被2整除。
再看下列代码:
是不是觉得很奇怪?ALIGN2 和 ALIGN3都是1个int型,1个char型,1个short型,可是它们所占的空间却1个是8,一个是12?这非常非常不科学啊!
2个结构体都拥有一样的成员变量,可是所占的大小却有很大的区别。这一切的一切,是计算机中的幽灵在作祟,还是另有隐情? 编译器如此厚此薄彼,到底是为什么?被偷去的内存,到底去了哪里?
下一篇我们将使用gcc编译,分析编译生成的每一步,了解编译器具体是怎么做的,为什么需要这么做,为你揭开这些谜团!!!
不要走开,后续更精彩,请关注本人博客后续更新 :-)