最近遇到很多关于计算sizeof的问题,它主要涉及到内存对齐的问题,简单的总结了一下:
内存对齐值的计算规则:
1.内存对齐值由编译指示和占用字节数最大的成员两者中较小的值决定;
2.成员的对齐的顺序就是声明的顺序;
3.如果一个成员已经对齐完成,占用的空间小于结构体的对齐值,那么下一个成员,当满足一定的条件时,可以不按照
对齐值进行对齐:上一个设置完成占用的字节数a,下一个成员占用的内存空间字节的数量x,对齐值为p,满足
p - a >= x;这样可以直接接着上一个成员分配,起始偏移量%x = 0;
内存对齐的原因:
1.平台移植
2.性能
内存对齐的编译器指示:通过#pragma pack(n) (n = 1, 2, 4, 8, 16)
实例:
#pragma pack(1)
struct A
{
int a; // 4
char b; // 1
double c; // 8
};
对齐的值为1,sizeof(A) = 13;
#pragma pack(2)
struct A
{
int a; // 4
char b; // 2
double c; // 8
};
对齐的值为2,sizeof(A) = 14;
#pragma pack(4)
struct A
{
int a; // 4
char b; // 4
double c; // 8
};
对齐的值为1,sizeof(A) = 16;
#pragma pack(8)
struct A
{
int a; // 4
char b; // 4
double c; // 8
};
对齐的值为1,sizeof(A) = 16;
#pragma pack(16)
struct A
{
int a; // 4
char b; // 4
double c; // 8
};
对齐的值为1,sizeof(A) = 16;
// 如果结构体的成员也是个结构体
#pragma pack(8)
struct B
{
int a;
char b;
double c;
};
struct A
{
int a;
char b;
double c;
B d;
};
sizeof(A) = 4 + 4 + 8 + sizeof(B) = 32
// 如果结构体的成员是个数组
#pragma pack(8)
struct A
{
int a;
char b;
double c;
char d[17];
};
sizeof(A) = 4 + 4 + 8 + 17 + 7 = 40
// 如果是个联合体
#pragma pack(8)
union DATE
{
char a;
int i[5]; 2 * (int) + 2 * (int) + (int) + 4 = 24
double b;
};
sizeof(DATE) = int[5]按照8个字节对齐 = 24