C语言结构体对齐详解

文章目录

  • 一、C语言结构体对齐大小快速判断
  • 二、反汇编角度看结构体
  • 三、总结


一、C语言结构体对齐大小快速判断

在C语言中定义一个结构体,里面具体占用多少个字节呢,先举一个例子,如下:

#include
#pragma pack(8)//交代按照8字节对齐宽度
struct A
{
	char x;//占用1字节
	char y;
	char z;
};
struct B
{
	char x;
	int y;//占用4字节
	char z;
};
int main()
{
	A a;
	B b;
	printf("%d\n", sizeof(a));//输出3
	printf("%d\n", sizeof(b));//输出12
	return 0;
}

通过上面的输出结果,我这里直接给出计算方法。
(1)确定结构体中每一个数据类型的占用宽度,以B这个结构体为例,分别是char占用1字节、int占用4字节、char占用1字节。
(2)确认程序的结构体对齐宽度,这里为8字节宽度
(3)分别以结构体中每一个数据类型宽度与对齐宽度比较,然后分别取较小的值,这里就是1、4、1与8分别比较,得到的是1、4、1
(4)取上一步得到值的最大值,作为对齐后空间的基数,即结构体对齐后的大小必为这个基数的整数倍,这里就是取1,4,1中的最大值为4作为基数
(5)结构体中每一个数据类型按照自身长度的整数倍依次排列在地址空间中,即char的起始空间可从0,1,2,3,XXX开始;int的起始空间可从0,4,8,12,XXX开始。
有了上面的步骤,我们对B结构体分析如下图所示。可以看出是占用12个字节。
B结构体占用空间描述
有了上面的分析步骤,我们再试试其他的

#include
#pragma pack(2)
struct B
{
	int x;
	short y;
	char z;
};
int main()
{
	B b;
	printf("%d\n", sizeof(b));//输出8
	return 0;
}

上面我们改成了2的对齐宽度,其占用空间大小如下所示:
结构体占用空间大小示意图
通过上面的分析,我们已经可以从源程序中分析出所占用的空间大小了。下面我们从反汇编的角度看看。

二、反汇编角度看结构体

C源代码如下:

#include
#pragma pack(2)
struct B
{
	int x;
	short y;
	char z;
};
int main()
{
	B b;
	b.x = 1;
	b.y = 2;
	b.z = 3;
	printf("%d\n", sizeof(b));//输出8
	while (1);
	return 0;
}

我们用OllyDBG得到反汇编,因为b变量是在main函数中定义的,因此其内存分配在main函数栈空间中,具体如下:
C语言结构体对齐详解_第1张图片
运行到push 0x8的时候,其函数栈中相关内容为:
栈空间
可以看出从00A1FE44地址开始往上增加,依次是4字节的int(值为1),2字节的short(值为2),1字节的char(值为3)以及1字节的值为CC(纠正上面正向分析中填00的地方实际应该是CC)

其实我这里有一点好奇,sizeof是如何在内存中确定结构体的大小的,毕竟从反汇编的角度来看,并不能直接看出来结构体所占用的空间大小。


三、总结

通过上面的描述,我们可以从正向、反汇编两个角度去理解C结构体占用的存储空间大小。

你可能感兴趣的:(C与C++学习,c语言,结构体大小)