Intel奉劝大家,如果想提升性能,那么所有的程序数据都应该尽可能地对齐。(~ ̄▽ ̄)~
为什么要内存对齐
其他少说,先看例子。ヾ(≧▽≦*)o 观察结构体A B ,发现两者的变量顺序不同
#include <bits/stdc++.h>
using namespace std;
struct A
{
char a;
int b;
short c;
};
struct B
{
char a;
short b;
int c;
};
struct C
{
char a;
char b;
short c;
int d;
};
struct D
{
char a;
short b;
char c;
int d;
};
int main()
{
cout<<"sizeof(a):"<<sizeof(A)<<endl;
cout<<"sizeof(b):"<<sizeof(B)<<endl;
cout<<"sizeof(c):"<<sizeof(C)<<endl;
cout<<"sizeof(d):"<<sizeof(D)<<endl;
return 0;
}
可以看出,输出结果为
sizeof(a):12
sizeof(b):8
sizeof(c):8
sizeof(d):12
可以看出 a,b使用的内存空间并不相同。 下面是他们占用的空间示意图。 问题来了:
为什么不是紧接着排序的?◑﹏◐
这个需要了解地址对齐
为了方便讲述,我们对地址对齐的规则进行一个简单定义(仅为帮助理解,并不严谨)
char 偏移量为sizeof(char) 即 1 的倍数
short 偏移量为sizeof(short) 即 2 的倍数
int 偏移量为sizeof(int) 即 4 的倍数
float 偏移量为sizeof(float) 即 4 的倍数
double 偏移量为sizeof(double) 即 8 的倍数
在结构体中,从结构体的首地址开始,假设地址从0开始。
对结构体A来说
- a 是 char 类型占 1 个字节,占从 0 ~ 0 的字节
- b 是 int 类型占 4 个字节,占从 4 ~ 7的字节
- c 是 short 类型占 2 个字节,从 8 ~ 9 的字节
对结构体B来说
a 是 char 类型占 1 个字节,占从 0 ~ 0 的字节
b 是 short 类型占 2 个字节,从 2 ~ 3 的字节
c 是 int 类型占 4 个字节,占从 4 ~ 7的字节
什么是内存对齐
说白了就是调整结构体中数据类型的顺序,使其最终占用空间尽可能小。 看结构体 C 和 D
对结构体C来说
- a 是 char 类型占 1 个字节,占从 0 ~ 0 的字节
- b 是 char 类型占 1 个字节,占从 1 ~ 1 的字节
- c 是 short 类型占 2 个字节,从 2 ~ 3 的字节
- d 是 int 类型占 4 个字节,占从 4 ~ 7的字节
对结构体D来说
- a 是 char 类型占 1 个字节,占从 0 ~ 0 的字节
- b 是 short 类型占 2 个字节,占从 2 ~ 3 的字节
- c 是 char 类型占 1 个字节,从 4 ~ 4 的字节
- d 是 int 类型占 4 个字节,占从 8 ~ 11 的字节
这里就很显著的看出来,结构体排序的顺序对于占用空间的影响还是比较大的。
总结
- C语言和C++中空类和空结构体的大小 在C++中规定了空结构体和空类的内存所占大小为1字节,因为c++中规定,任何不同的对象不能拥有相同的内存地址。 而在C语言中,空的结构体在内存中所占大小为0。(gcc中测试为0,其他编译器不一定)
- 不是所有的语言都需要内存对齐,一些语言自动提供内存对齐
- 为什么要内存对齐?
- 1.平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
- 2.性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。