sizeof的对齐问题是C/C++里面一个比较经典的问题,在了解这些问题之前我们首先需要有一些先验知识。
C/C++ 不同数据占用内存大小
数据类型 | 32位 | 64位 |
---|---|---|
char | 1 | 1 |
int | 4 | 大多数时候为4,少数为8和编译器有关 |
short | 2 | 2 |
long | 4 | 8 |
float | 4 | 4 |
double | 8 | 8 |
sizeof的用法
sizeof 是一个关键字,它是一个编译时运算符,用于判断变量或数据类型的字节大小。
sizeof 运算符可用于获取类、结构、共用体和其他用户自定义数据类型的大小。
使用 sizeof 的语法如下:
sizeof(type datatype);
对于简单数据类型有sizeof(int)=4,sizeof(double)=8。对于数组而言有
#include<iostream>
using namespace std;
int main()
{
int a[3];
cout<<sizeof(a);
return 0;
}
最后的输出结果为12。所以数组的大小即为数组数 sizeof(datatype)。
结构体对齐问题
对于结构体而言,存在一个对齐问题,不能简单的将里面成员大小相加。例如:
typedef struct s
{
int a;
char c;
int j;
};
如果和数据一样处理,那么会有sizeof(s)=9,但是实际运行结果如下:
为什么会出现这种情况呢?这里我们先要知道编译器在编译时会遵循的两条原则
(1)结构体变量中成员的偏移量必须是成员大小的整数倍(0被认为是任何数的整数倍)
(2)结构体大小必须是所有成员大小的整数倍,也即所有成员大小的公倍数。
首先解释下偏移量,偏移量指的是结构体成员地址与结构体地址之间的差。所以a的偏移量为0,c的偏移量必须为成员的倍数,其实也是最小公倍数,即偏移量为4。而j的地址就变成了4+1=5,此时会补齐3位,这样才满足(1),因此j的偏移量为8。因此结构体的大小为8+4=12。如果对于这个例子还是不理解,可以看看下面两个例子:
typedef struct s1
{
char a;
char c;
int j;
};
typedef struct s2
{
int a;
double b;
char c;
};
所以根据上面两条原则,sizeof(s1)=8,sizeof(s2)=24。
至于结构体里嵌套结构体,其实就是将嵌套结构体当成一个成员来分析,其他都是一样,就不在赘述。