首先我们都知道结构体是多个变量的集合,在其中可以存放整型,浮点型等等各种,然后结构体内存是如何对齐的呢,他并不是按连续顺序去排下去的,首先我们先上一段代码
#include<iostream>
#include<cstdlib>
using namespace std;
struct a{
int m;
char n;
double c;
};
struct b{
char o;
double p;
int j;
};
int main()
{
cout << sizeof(a) << endl;
cout << sizeof(b) << endl;
system("pause");
}
这段代码运行出来的结果得出a的内存大小为16,b的内存大小为24,同样的三个类型,只是排列顺序不同,结构体的大小就不一样。下面是对齐规则
结构体内存对齐规则
1. 第一个成员在与结构体偏移量为0的地址处。
2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
对齐数 = 编译器默认的一个对齐数 与 该成员大小相比中的较小值。
VS中默认的对齐数为8,gcc中的对齐数为4
3. 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。
4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是
所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
那么为什么要内存对齐呢
内存对齐大大提高了cpu的读取速率。
1.还有并非所有硬件平台都可以访问任何地址上的任何数据,有些硬件平台也只能访问某些特定地址处某些特定类型的数据。
2.内存对齐的CPU只需要读取一次,没有内存对齐,CPU则需要读取两次。
如何让结构体按照指定的对齐参数进行对齐
设置对齐参数可在结构体struct之前加上#pragma pack(对齐数),在struct之后加上#pragma pack;便可以设置对齐参数
如何知道结构体中某个成员相对于结构体起始位置的偏移量
我们可以使用这个#define offsetof(s,a) (size_t) (((s*)0)->a),这个用法就是我们告诉编译器有一个指针指向结构体s,而它的值是0,然后我们取结构体中的a,a的地址就是a的偏移量了。
#include<iostream>
#include<cstdlib>
using namespace std;
#define offsetof(s,a) (size_t) &(((s*)0)->a)
struct a{
int m;
char n;
double c;
};
#pragma pack(4)
struct b{
char o;
double p;
int j;
};
#pragma pack;
int main()
{
cout <<"a的内存大小为"<< sizeof(a) << endl;
cout <<"b的内存大小为"<< sizeof(b) << endl;
cout << offsetof(b, p) << endl;
system("pause");
}