运算符sizeof()可以计算出给定类型的大小,对于32位系统来说,sizeof(char) = 1, sizeof(int) = 4。基本数据类型的大小很好计算,那计算构造数据类型的大小也是这样简单吗?
C语言中的构造数据类型有三种:数组,结构体和共用体。
1. 数组是相同类型的元素的集合,只要会计算单个元素的大小,整个数组所占空间等于基础元素大小乘以元素的个数
2. 结构体中的成员可以是不同的数据类型,成员按照定义时的顺序一次存储在连续的内存空 间。和数组不一样的是,结构体的大小不是所有成员简单的相加,需要考虑到系统在存储结 构体变量时的地址对齐问题。
这里先介绍偏移量的概念:偏移量指的是结构体变量中成员的地址和结构体变量地址的差。结构体大小等于最后一个成员的偏移量加上最后一个成员的大小。显然,结构体变量中第一个成员的地址就是结构体变量的首地址。因此第一个成员的偏移量为0,第二个成员的偏移量为第一个成员的偏移量加上第一个成员的大小,第三个成员的偏移量为第二个成员的偏移量加上第二个成员的大小,... ...
However,在实际中,存储变量时地址要求对齐,编译器在编译程序时会遵循两条原则:
1. 结构体变量中成员的偏移量必须是成员大小的整数倍(0被认为是任何数的整数倍)
2. 结构体大小必须是所有成员大小的整数倍,也即所有成员大小的公倍数
这里举一个例子:
struct Student
{
int age;
char gender;
int weight;
}Stu;
用sizeof()求该结构体的大小,你会发现sizeof(Stu) = 12。但int占4个Byte,char占1个Byte,weight占4个Byte,加起来应该是9啊?
根据以上概念,可以知道----Stu中,第一个成员age的偏移量为0(1.偏移量是成员大小的整数倍),大小为4;所以第二个成员gender的偏移量为4(1.偏移量是成员大小的整数倍),大小为1;如果按照sizeof(Stu)=9的计算方法,Stu的第三个成员的偏移量是5(?怎么会,按照"1. 结构体变量中成员的偏移量必须是成员大小的整数倍"),但它的偏移量应该是8,大小为4。所以,结构体Student的大小就该是(4,1,4)的公倍数,又得能装得下所有成员,所以是12。
另外,有一点,对于拥有相同数据成员的两个结构体,如果成员的排序方式不同,其结构体大小也不一样。