C语言知识梳理——结构体内存对齐

C语言知识梳理——结构体内存对齐

首先,请计算一下该结构体的大小:

struct S
{
	char a;
	int b;
	char c[10];
	double d;
	char e;
	char f;
};

正确答案是:40

在计算结构体的大小时,如果只是简单的将结构体内的成员变量大小加总,那就是经典的错误,标准的0分。结构体大小的计算,不同于简单的单变量大小计算,其中涉及到内存对齐相关知识。

结构体内存对齐的规则如下:

1、第一个成员的位置在与结构体变量偏移量为0的地址处。
简言之,就是第一个成员变量无论是什么类型,都是放在这个结构体变量的初始地址处。

2、 其他成员变量要对齐到对齐数的整数倍地址处。
对齐数=min{编译器默认的对齐数,该成员的大小} ;
在VS环境下对齐数的默认值为8,将8与成员的大小比较取较小值作为最终对齐数;
在Linux环境下无默认对齐数,对齐数就是成员自身的大小。

3、结构体总大小为最大对齐数(max{成员1,成员2……})的整数倍。
此处的最大对齐数取所有成员变量最终对齐数的最大值。

4、 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
一个结构体内部还嵌套结构体的情形下,还需要考虑内部嵌套结构体的内部成员的最大对齐数,在计算整个结构体的大小时,需要将这一对齐数和结构体内其他成员对齐数相比,取最大对齐数的整数倍作为结构体的大小。

了解了计算规则后,就可以计算本文开头的结构体大小了。

struct S
{
	char a;//0
	int b;//4-7
	char c[10];//8-17  (对数组而言,对齐数看的是数组内部元素类型的大小)
	double d;//24-31
	char e;//32
	char f;//33
};//目前共占据0-33即34个字节,最大对齐数是8,结构体总大小是8的整数倍,因此最终答案是40

如果想要修改系统默认的对齐数,可以利用预处理指令:

#pragma package(对齐数)
括号里为空,则恢复默认值

从上述例题中不难发现,结构体对齐导致占用空间增大,为了能够在满足对齐的条件下节省空间,可以将占用空间小的放在一起,例如将上述结构体优化后:

struct S
{
	char a;//0
	char e;//1
	char f;//2
	int b;//4-7
	char c[10];//8-17
	double d;//24-31
};//此时占据0-31共32个字节,最大对齐数为8,结构体大小为8的整数倍32,空间节省了8个字节

结构体内存对齐是一种拿空间换取时间的做法:
例如32位的计算机,CPU一次能处理32bit的数据。以int类型为例,如果没有内存对齐,那么很可能一个int类型的数据需要两次才能处理完毕,但是内存对其之后,只需要一次就能处理完毕,提升了运行效率。

(注:本文基于VS2019,如有错误欢迎各位指正)

你可能感兴趣的:(c语言)