我们实际生活中,保存的数据一般不会是同一种类型,所以引入了结构体。而结构体的大小也不是成员类型大小的简单相加。需要考虑到系统在存储结构体变量时的地址对齐问题。
由于存储变量地址对齐的问题,结构体大小计算必须满足两条原则:
一、结构体成员的偏移量必须是成员大小的整数倍(0被认为是任何数的整数倍)
二、结构体总大小必须是所有成员大小(数组,结构体除外)的整数倍
对齐方式很浪费空间,确实。。 可是按照计算机的访问规则,这种对齐方式提升了效率
#include <stdio.h>
#include <stdlib.h>
struct s1{
char ch1; //1
char ch2; //1
int i; //4 遵循结构体运算法则第一条,偏移量必须是当前成员的大小整数倍,逻辑偏移2 实际按照对其的规则,要偏移4
};
struct s2{
char ch1; //1 {} {}{}{} {}{}{}{}
int i; //4 +3
char ch2; //1 9 ?12
};
struct s3{
char ch1; // 1
int i; // 4 3
char str[14]; // 14 22
};
struct s4{
char ch1; //1
int i; //4 3
struct s{
char ch1; //1
int j; //4 3
double d; //8
};
float t; //4 12
};
struct s5{
char ch1; //1
int i; //4 3
struct ss{
char ch1; //1
int j; //4 3
double d; //8
}stmp;
float t; //4 32
};
struct s6{
char ch1; //1
int i; //4 3
union{ //联合体只看最大的
char ch2; //1
int j; //4
};
};
#pragma pack(4) //指定向4对齐 这里最大是8
struct s7{ //如果成员的大小超过了pack要求的,就按pack来对齐,
char ch1; //如果最大成员大小没有超过pack,结构体的总大小,就按最大成员大小来对齐
int i;
float f;
double d;
};
#pragma pack(10) //指定向10对齐 超过了这里最大的8 ,得按照8来算
struct s8{
char ch1;
int i;
float f;
double d;
};
int main()
{
printf("char:%d\n",sizeof(char));
printf("float:%d\n",sizeof(float));
printf("int:%d\n",sizeof(int));
printf("double:%d\n",sizeof(double));
printf("s1:%d\n",sizeof(struct s1));
printf("s2:%d\n",sizeof(struct s2));
printf("s3:%d\n",sizeof(struct s3));
printf("s4:%d\n",sizeof(struct s4));
printf("s5:%d\n",sizeof(struct s5));
printf("s6:%d\n",sizeof(struct s6));
printf("s7:%d\n",sizeof(struct s7));
printf("s8:%d\n",sizeof(struct s8));
system("pause");
return 0;
}
运算结果:
char:1
float:4
int:4
double:8
s1:8
s2:12
s3:24
s4:12
s5:32
s6:12
s7:20
s8:20