首先,从一个计算结构体字节大小的问题开始:
问题:在32位的编译系统中有如下结构体定义
typedef struct
{
int A;
char B;
}T_S;
问,T_S的大小是多少字节?
答案:其实这个题目本身并不严谨,T_S的大小跟编译器以及编译选项是有关系的。
首先,在pc上一般编译器都会做内存对齐,这个主要有两方面的原因:
一、平台原因(移植原因),不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
二、性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。
对齐系数可以是1,2,4,8,16。一般来讲,对于32位的编译器默认采用4位对齐,但是也有一些嵌入式系统默认是不对齐的。可以通过预编译命令#pragma pack(n)改变默认对齐方式,其中n为对齐系数。另外,这个也和平台有关,在一些机器上int并不是32位的。
但是有一点需要注意的事,预编译命令#pragma pack(n)并不一定总是生效。就拿本题来说,A为4位,B为1位,如果我们指明要用8来对齐,则我们需要给B补上7位,如果是16对齐则要补15位,这是对空间的严重浪费^-^……编译器肯定不会容忍我们这样挥霍的,所以实际的对齐方式采用 [pack指定的对齐长度]和[struct中最长成员的长度]较小的一个,这样既满足了cpu的对齐要求又可以尽量减少空间的浪费。
对于本题,如果采用缺省对齐方式,则sizeof(T_s)等于8,其中A为4位,B为1位,补齐3位;
如果采用#pragma pack即不做对齐处理,则sizeof(T_s)等于5,其中A为4位,B为1位;
如果采用2对齐,则sizeof(T_s)等于6,其中A为4位,B为1位,补齐1位;
如果采用8对齐,则sizeof(T_s)等于8,其中A为4位,B为1位,补齐3位;
如果采用16对齐,则sizeof(T_s)等于8,其中A为4位,B为1位,补齐3位;