结构体内存对齐与类内存对齐
为什么有内存对齐???
“内存对齐”应该是[编译器][Link 1]的“管辖范围”。编译器为程序中的每个“[数据单元][Link 2]”安排在适当的位置上,便于编译器管理数据。但是C语言的一个特点就是太灵活,太强大,它允许你干预“内存对齐”。如果你想了解更加底层的秘密,“内存对齐”对你就不应该再透明了。对于内存对齐问题,主要存在于struct和union等复合结构在内存中的分布情况,许多实际的计算机系统对基本类型数据在内存中存放的位置有限制,它们要求这些数据的首地址的值是某个数M(通常是4或8);对于“内存对齐”,主要是为了提高程序的性能,数据结构,特别是栈,应尽可能在自然边界上对齐,经过对齐后,cpu的内存访问速度大大提升。
结构体内存对齐规则:
- 第一个成员在与结构体偏移量为0的地址处。
- 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
- 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。
如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
注意:对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。VS中默认的对齐数为8,gcc中的对齐数为4
举个栗子:
struct A1{
int a;
double b;
char c;
char d;
};
struct A2 {
int a;
char c;
char d;
double b;
};
struct A3
{};
int main()
{cout << sizeof(A1) << " " << sizeof(A2) << " " << sizeof(A3) << endl;
system("pause");
return 0;
}
结果显示:
分析:
为什么空的结构体大小为1???
你想想,如果我们把struct student 看成一个模子的话,你能造出一个没有任何容积的模子吗?显然不行。编译器也是如此认为。编译器认为任何一种数据类型都有其大小,用它来定义一个变量能够分配确定大小的空间。既然如此,编译器就理所当然的认为任何一个结构体都是有大小的,哪怕这个结构体为空。那万一结构体真的为空,它的大小为什么值比较合适呢?假设结构体内只有一个char 型的数据成员,那其大小为1byte(这里先不考虑内存对齐的情况).也就是说非空结构体类型数据最少需要占一个字节的空间,而空结构体类型数据总不能比最小的非空结构体类型数据所占的空间大吧。这就麻烦了,空结构体的大小既不能为0,也不能大于1,怎么办?定义为0.5个byte?但是内存地址的最小单位是1 个byte,0.5 个byte 怎么处理?解决这个问题的最好办法就是折中,编译器理所当然的认为你构造一个结构体数据类型是用来打包一些数据成员的,而最小的数据成员需要1 个byte,编译器为每个结构体类型数据至少预留1 个byte的空间。所以,空结构体的大小就定位1 个byte。
类的存储方式:
与结构体类似,一个类的大小,实际就是该类中”成员变量”之和,当然也要进行内存对齐,注意空类的大小也为1,编译器给了空类一个字节来唯一标识这个类。
举个栗子:
class A1 {
public:
void f1(){}
private:
int _a;
};
// 类中仅有成员函数
class A2 {
public:
void f2() {}
};
// 类中什么都没有---空类
class A3
{};
int main()
{
cout << sizeof(A1) << " " << sizeof(A2) << " " << sizeof(A3) << endl;
system("pause");
return 0;
}
即类中关注“成员变量”!!!空类大小为1!!!
还没有评论,来说两句吧...