首先我们大家先思考一个问题,为什么编译器会有内存对齐这种东西呢?
原因有二:
一.平台原因:
某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
二.性能原因:
如果访问的是未对齐的内存,处理器需要做两次内存访问;如果内存对齐,则处理器只需要做一次内存访问。
许多计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据的首地址的值是某个数k(通常为4或8)的倍数,这就是所谓的内存对齐,而这个k则被称为该数据类型的对齐模数。
内存对齐的规定:
1.数据成员对齐规则:结构的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员自身大小的整数倍开始。
2.结构体作为成员:如果是两个结构体嵌套在一起,则在计算字节大小的时候应该先找出第一个最大对齐模数和第二个函数体的最大对齐模数比较,找出最大的那个数,就是整个函数的最大对齐模数,然后用它的整数倍计算存储。
3.结构体成员相对首地址偏移量必须是成员大小的整数倍,也就是内存对齐。
4.结构体总大小必须是对齐模数的整数倍。
内存对齐只能加不能减,在存储类型不同的数据的时候,它们所占的字节大小也不同,在计算时是看前边所有数据之和是否为k的倍数,而不是从上一节补。
位域
什么是位域?
位域就是把一个字节中的二进制划分为几个不同的区域,并说明每个区域的位数。
一.位域的定义和位域的变量说明与结构体定义相仿,形式为:
struct 位域结构名
{位域列表};
其中位域列表的形式为: 类型说明符 位域名:位域长度
ex:
struct A
{
int a:8;
int b:2;
int c:6;
};
位域的存储要求
1,一个位域必须存在同一个字节中,不能跨越两个字节(1个字节8个位)。
ex:
struct A
{
int a:5;
int b:4;//从下一个字节开始存放
int c:6;
};
2.位域可以无位域名,这时它只能用做填充或调整位置,不能使用。
ex:
char :2 //该2 位不能使用
在计算位域的大小时,如果位域字段穿插着非位域字段,则不进行压缩。
ex:struct B
{
char c:1;
double i;
int c2:4;
};
cout<<sizeof(B)<<endl;//13
struct B
{
char c:1;
int c2:4;
double i;
};cout<<sizeof(B)<<endl;//9