内存对齐其实是为了在程序运行的时候更快的查找内存而做的一种编译器优化。
我们先看这样一个例子:
1 #include <iostream> 2 using namespace std; 3 4 struct vpoet 5 { 6 int a; //4 bytes 7 char b; //1 bytes 8 double c; // 8 bytes 9 char *d; //4 bytes 10 int e; //4 bytes 11 }; 12 13 int main() 14 { 15 cout<<"sizeof(vpoet)="<<sizeof(vpoet)<<endl; 16 return 0; 17 }
运行结果:
这个结构体大小为24个字节,但是我们仔细算一算其字节数
发现其实际上只有4+1+8+4+4=21个字节,那是如何算
出来24个字节的呢,其实在默认情况下编译器是按照结构体
中所占字节最大的成员来进行内存对齐的。比如在结构体
vpoet中最大的是double double占8个字节,那么编译器
默认按8个字节的方式对齐那么编译器将按照大于实际字节数
的double最小整数倍来进行内存分配。因而这里实际是在结构体
的成员b后面填充了三个字节用于对齐。
那么问题来了,对齐方式可以改吗?
可以我们可以在文件头加上
1 #pragma pack(n)
来改变内存对齐的字节数
比如当我们按照一个字节对齐的时候:
1 #include <iostream> 2 using namespace std; 3 #pragma pack(1) 4 5 struct vpoet 6 { 7 int a; //4 bytes 8 char b; //1 bytes 9 double c; // 8 bytes 10 char *d; //4 bytes 11 int e; //4 bytes 12 }; 13 14 int main() 15 { 16 cout<<"sizeof(vpoet)="<<sizeof(vpoet)<<endl; 17 return 0; 18 }
运行结果:
当我们按照1字节对齐的时候,编译器将为
该结构体分配本身实际大小的字节数
当我们以2字节对齐的时候
1 #pragma pack(2)
此时的输出结果为:
当我们按照2字节对齐的时候,编译器将为结构体
成员b后面填充一个空字节用于内存对齐。
记住这样一个规律:
默认情况下编译器将按照实际结构体中占内存字节数
最大的成员的整数倍进行分配,该最大的整数倍
应正好大于或者等于结构体实际所占的内存字节数
时间: 2024-10-31 07:30:40