首先定义一个结构体
struct object{
char a;
char b;
int c;
};
要求该结构体类型的字节大小,需要了解结构体内存对齐,以下是结构体内存对齐的相关规则:
1)第一个成员变量在与结构体变量偏移量为0的地址处;
2)其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处;
对齐数=编译器默认的一个对齐数与该成员大小的较小值;
规定VS编译器的对齐数默认值为8,gcc无默认对齐数;
3)结构体总体大小为最大对齐数的整数倍;
4)对于嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍;
以上就是官方语言给出的规则,这样看是很难看懂的,接下来用一个例子来演示一遍就简单明了了。以文中开始定义的结构体为例:
在下面我们可以验证一下我们的分析是否正确
由此可见我们的分析是正确的。
如果把原来的结构体
struct object{
char a;
char b;
int c;
};
改为
struct object{
char b;
int c;
char a;
};
那么该结构体的大小是否还会是8呢?我们画图分析一下:
由图可发现,该结构体占用了9个内存空间,那么该结构体所占内存大小就是9吗?我们先来验证一下:
怎么会是12呢?
因为该结构体中最大的数据类型所占的内存空间是4,而9不是4的整数倍,所以在原来所占的9个内存的基础上还要再浪费3个内存空间才可以,所以该结构体所占的内存大小为12。
我们可以发现,尽管结构体中的数据的类型和相同类型的个数也相同的情况下,不同的排列顺序会导致该结构体所占用的内存空间也会有所不同,可以得到一个结论:若要结构体内存占的最小,把内存小的数据类型的数据放在结构体的前面即可。
对于结构体嵌套来说,内存大小的计算仅有一点小小的改变,举个例子:
struct object{
char a;
char b;
int c;
};
由上面的解析我们知道该结构体内存大小为8
struct subject{
Int q;
Struct object w;
char e;
};
对于该结构体来说,内存是多少呢?
我们先来分析一下:
我们验证一下:
那么,为什么存在内存对齐呢?
1)平台原因:不是所有的硬件平台都能访问任意地址上的任意数据的,某些硬件平台只能在某些地址处取某些特定数据类型的数据,否则抛出硬件异常;
2)性能原因:数据结构应尽可能在自然边界对齐,原因在于为了访问未对齐的内存,处理器需要做两次内存访问,而对齐的数据,内存访问只需要一次就够。
总的来说:结构体的内存访问是拿空间来换时间的做法。