sizeof(结构体)的大小判断

1.偏移量

在讨论结构体的字节大小之前,先说一下偏移量的概念,偏移量指的是结构体变量中成员的地址和结构体变量地址的差。结构体变量中第一个成员的地址就是结构体变量的首地址。因此,一般情况下(后续会讨论特殊情况)结构体中的第一个成员的偏移量为0,结构体的字节大小为最后一个成员的偏移量+该成员的字节大小。也就是说,和数组不一样的是,结构体的大小不是所有成员大小简单的相加,需要考虑到系统在存储结构体变量时的地址对齐问题。代码如下所示:

struct s
{
	char a;
	char b;
	int c;
};

上述代码中定义了一个结构体s, 在结构体之中,第一个成员a的偏移量为0,第二个成员b的偏移量是第一个成员的偏移量+第一个成员的大小(0+1)其值为1,后续按照此规律,后一个成员的偏移量=上一个成员的偏移量+上一个成员的字节大小;

注意:按照此规律,第三个成员c的偏移量是第二个成员的偏移量应该是加上第二个成员的大小(1+1)其值为2,但是事实并不是这样,在实际中,存储变量时地址要求对齐,编译器在编译程序时会遵循两条原则:

(1)结构体变量中任何一个成员的偏移量必须是该成员字节大小的整数倍(0被认为是任何数的整数倍)

(2)结构体大小必须是所有成员大小的整数倍,即要能够整除所有成员的字节大小;

前两个成员均符合要求,但第三个成员的偏移量为2,并不是自身(int)大小的整数倍。编译器在处理时会在第二个成员后面补上2个空字节,使得第三个成员的偏移量变成4。这里在补字节时注意:

只需要找到最近的能够整除字节大小的数就行,例如,2无法整除4,但补到4,4本身可以整除4,但是4往上还有8,12,16等等,只需到4即可,遇见整除就可以停,无需继续。

结构体大小等于最后一个成员的偏移量加上其大小,上面的例子中计算出结构体大小为:最后一个成员的偏移量+该成员的字节大小,即4(偏移量)+4(字节大小)=8;而且,8也是所有成员大小的整数倍

printf("%d\n", sizeof(struct s));//8

2.同类型不同顺序

struct ss
{
	char a;//偏移量为0
	char b;//偏移量为0+1=1
	int c;//偏移量为1+1=2,为了凑成int的整数倍,int为4字节,补两个字节,最终int c偏移量为4;
};
//最后结构体的字节大小为4+4=8;

struct tr
{
	char a;//偏移量为0
	int c;//偏移量为4;
	char b;//偏移量为8;
};
//8+1=9,9无法整除所有成员的字节大小,所以往上补,直到12,且12可以整除所有的字节数

结构体中成员顺序会对最终结构体的字节大小有一定影响,代码如上。

虽然结构体ss和tr中成员都一样,但sizeof(struct ss)的值为8而sizeof(struct tr)的值为12。

   

 printf("%d\n", sizeof(struct ss));//8
 printf("%d\n", sizeof(struct tr));//12

由此可见,结构体类型需要考虑到字节对齐的情况,不同的顺序会影响结构体的大小。

3.嵌套的结构体

对于嵌套的结构体,需要将其展开。对结构体求sizeof时,同时也有两个原则:

1.嵌套的结构体中,第一个成员的偏移量,必须是被嵌套的结构体中那个字节数最大的成员的整数     倍;

2.在计算有嵌套的结构体的字节时,要把其里面嵌套的结构体展开,然后按照上述相同的方法依次     计算偏移量;

struct strr
{
	short i;//偏移量0
	struct
	{
		char c;//偏移量4
		int j;//偏移量8
	} aa;
	int k;//偏移量12(上面的int j的偏移量为8,8加它本身的字节数4,即8+4=12)
};

结构体strr的成员aa.c的偏移量应该是4(被嵌套的结构体中最大成员为int,要为int的整数倍),而不是2。整个结构体大小应该是16(12+4)

4.结构体中包含数组

struct array
{
	float f;//偏移量0
	char p;//偏移量4
	int  arr[3];//偏移量5,不满足要求,要补到8
}array;

在含有数组的结构体中,该数组偏移量要补充至该数组类型的字节整数倍,而不是数组本身的字节,例如:int arr[3]偏移量为5,不满足要求,需要补充字节,但不是补充到12,而是4的整数倍

结果是8+12=20(数组的偏移量+数组的字节数)

注意:假如,最后结构体字节数并没有能够直接整除任何一个成员,依旧要补充到能够整除所有成员字节大小为止,例如:

struct s2  
{  
      int i;  //偏移量为0
      short m;  //偏移量为4
};

上述代码中,第一个成员偏移量为0,第二个成员偏移量为4,均符合要求;但是,按照计算方法,最后的结构体字节数为4+2=6,6无法整除所有成员的字节数大小,所以,需要继续补充字节至8,

所以该结构体最后的字节数为8;

printf("%d\n",sizeof(struct s2));//8

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值