一、结构体内存对齐
分析如下代码:
struct s{
char a;
int b;
char c;
};
两个char类型加上一个int类型一共6个字节?但是事实却是: 这是因为存在结构体内存对齐,指每个变量所占空间的起始处是有规定的,跟对齐数有关。 对齐数:每个变量的对齐数是编译器默认的对齐数与其所占内存大小的较小值。
- 首先结构体第一个变量所占内存的起始处我们假设为相对偏移量为0。
- 其余变量计算自己的对齐数,将自己所占内存的起始处从对齐数的整数倍处开始存放。
- 结构体所占内存总大小为其变量中最大对齐数的整数倍。
- 若结构体A的变量中有个是结构体B,那结构体B的对齐数为B内的变量的对齐数的最大值。
对齐数的存在是一种空间换时间的操作,方便了取数据时访问内存节约时间。
但是,为了可以也相对节省空间,可以把占用空间小的变量放在一起,可以节省空间,看如下例子:
struct s1{
char c1;
int i;
char c2;
};
上述代码结构题s1所占内存为12个字节。那么做如下改进:
struct s2{
char c1;
char c2;
int i;
};
可见结构题s2所占内存大小为8字节,比s1少了4字节。
二、位段
位段的形式如下:
struct S{
int _a:2;
int _b:5;
int _c:10;
int _d:30;
};
: n 代表前面的变量占多少个bit(不是字节,是比特位)
位段内存分配原则:
- 位段的成员可以是int、unsigned int、char等整形家族的类型。
- 分配时按照需要4个字节一次分配或者1个字节一次分配。
上面的位段C,因为其为int类型,直接一次分配4个字节,32bit。_a分配两个bit,_b分配5个bit,_c分配10个bit,此时一开始分配的4个字节还剩15个bit不够_d了,因为再分配4个字节,共8个字节。 (至于第一次分配剩下的15bit,_d是用完这15bit再去用新分配的还是直接用新分配的,这个不同的编译器实现不同,C没有明确规定怎么办,故位段存在不少跨平台问题)
相比于结构题,位段可以达到一样的效果,但是更加节省空间
|