结构体的大小不是成员类型大小的简单相加。需要考虑到系统在存储结构体变量时的地址对齐问题。
一、结构体计算方法(规则)
由于存储变量地址对齐的问题,结构体大小计算必须满足两条原则:
1.结构体成员的偏移量必须是成员大小的整数倍(0倍认为是任何数的整数倍)
- 结构体大小必须是所有成员大小(数组,结构体除外)的整数倍。(结构体声明不算进去,但定义了变量就算进去)
二、对齐方式浪费空间?
浪费,但是按照计算机的访问规则,这样对齐大大提升了访问效率
三、例子
struct S1{
char ch1; //1 1
char ch2; //1 2
int i; //4 8 遵循第一条,逻辑偏移2,实际按照第1条对其规则,偏移4
};
//8
【ch1】 【ch2】 【】 【】
【i】 【i】 【i】 【i】
struct S2{
char ch1; //1
int i; //4
char ch2; //1
};
//如果按照第1条规则,应该是9,但是还要满足第2条规则,结构体大小必须是每个成员的整数倍
//12
【ch1】 【】 【】 【】
【i】 【i】【i】【i】
【ch2】 【】 【】 【】
struct S3{
char ch; //1
int i; //4
char src[13]; //13
};
//1,8,21,因为21不是4的整数倍,所以是24
//24
struct S4{
char ch; //1
int i; //4
struct s{ //8
char ch1;
int j;
};
float f; //4
};
//遵循第2条,不算结构体声明,是12
//12
struct S4{
char ch; //1
int i; //4
struct s{ //8
char ch1;
int j;
}stmp; //定义了结构体,大小加进去,但是不算倍数
float f; //4
};
//遵循第2条,结构体定义了算进去,是20
//20
struct S5{
char ch; //1
int i; //4
union{ //4
char ch1;
int j;
};
};
//联合体只算占用空间最大的union,是int 4个字节
//12
pragma pack()
结构体最大对齐超过10就按10
没超过就按结构体最大的对齐
pragma pack(4)
struct S6{
char ch; //1
int i; //4
float f; //4
double d; //8
};
//#pragma pack(4),对齐方式限制,有超过4的就按照4对齐,对齐4,所以是20,不是24
//20
pragma pack(10) //这里可能会有警告
//warning: alignment must be a small power of two, not 10 [-Wpragmas]
#pragma pack(16) //改为16就没警告了
struct S7{
char ch; //1
int i; //4
float f; //4
double d; //8
};
//#pragma pack(10),对齐方式限制,没超过10,就按照最大的对齐,对齐8,所以是24
//24