(C语言)结构体内存对齐

目录

1.对齐规则

2.示例

例1

 例2

 例3

3.存在内存对齐的原因

1.平台原因

2.性能原因

4.修改默认对齐数


1.对齐规则

(1)结构体的第一个成员放在偏移量(相较于结构体变量的起始位置)为0的位置

(2)从第二个成员起,之后的每个成员都要对齐到对齐数整数倍的地址处

        对齐数:编译器默认的对齐数与该成员大小的较小值

        VS中默认为8

        Linux中无默认对齐数,对齐数就是成员自身大小

(3)结构体总大小为最大对齐数(所有成员对齐数的最大值)的整数倍

(4)如果出现嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍

(5)当出现数组,数组的对齐数为数组元素与默认对齐数的较小值

2.示例

以下均在VS下实现

例1

#include <stdio.h>

struct s1
{
	char c1;
	int i;
	char c2;
};

int main()
{
	printf("%d", sizeof(struct s1));//12
	return 0;
}

计算结果为12,我们结合内存分布图来计算

c1为char类型,占1个字节,第一个成员放在偏移量为0的位置,(char的对齐数为1)

i为int类型,占4个字节,因此从偏移量为4的位置开始存放

c2为char类型,占1个字节,1为c2的默认对齐数,因此在i的后面接着存放c2,放在偏移量为9的位置处

结构体的最大对齐数为4,结构体的总大小为最大对齐数的整数倍,此时已经使用了9个字节的空间,则结构体的大小为12

 

 例2

#include <stdio.h>

struct s1
{
	char c1;
	int i;
	char c2;
};

struct s2
{
	char c;
	struct s1 s;
	int i;
};

int main()
{
	printf("%d\n", sizeof(struct s1));//12
	printf("%d\n", sizeof(struct s2));//20
	return 0;
}

计算结果为20

c为char类型,占1个字节,第一个成员放在偏移量为0的位置,(char的对齐数为1)

由例1计算得出s的大小为12,s为结构体类型,对齐到自己的最大对齐数的整数倍处,s中的3个成员分别为char、int、char类型,最大对齐数为4,因此s对齐到偏移量为4的地址空间处。

i为int类型,对齐数为4,因此对齐到偏移量为16的地址空间处。 

此时已经使用20个字节的空间,结构体的最大对齐数为4,因此结构体的大小为20

 

 例3

#include <stdio.h>

struct s3
{
	char c1;
	int arr[2];
	char c2;
};

int main()
{
	printf("%d\n", sizeof(struct s3));//16
	return 0;
}

 c1为char类型,占1个字节,第一个成员放在偏移量为0的位置,(char的对齐数为1)

arr[2]为数组,当出现数组时,对齐数为元素大小与默认对齐数的最小值,arr[2]的元素为int类型,对齐数为4,因此对齐到偏移量为4的地址空间处

c2为char类型,占1个字节,1为c2的默认对齐数,因此在arr[2]的后面接着存放c2,放在偏移量为12的位置处

3.存在内存对齐的原因

1.平台原因

并不是所有的硬件平台都可以访问任意地址上的任意数据。某些硬件平台只能在某些地址处取得某些特定类型的数据,否则会抛出硬件异常。

2.性能原因

数据结构(尤其是栈)应该尽可能地在自然边界上对齐。

原因:为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问

可以说,结构体的内存对齐是拿空间时间  

当在使用结构体时,为了满足对齐,同时节省空间,可占用空间小的成员尽量集中在一起

4.修改默认对齐数

结构在对齐方式不合适时,可以自己修改默认对齐数

使用#pragma预处理指令,可以修改默认对齐数(通常设置为2的次方数)

#include <stdio.h>

#pragma pack(4)//设置默认对齐数为4
struct s1
{
		//  成员大小  默认对齐数  对齐数
	char c;//  1			4		1
	double d;//8			4		4
	int i;//   4			4		4
};
#pragma pack()//取消设置的默认对齐数,还原为默认对齐数

struct s2
{
	//  成员大小  默认对齐数  对齐数
	char c;//  1			8		1
	double d;//8			8		8
	int i;//   4			8		4
};
int main()
{
	printf("%d %d", sizeof(struct s1),sizeof(struct s2));
	return 0;
}

struct s1

struct s2

猜你喜欢

转载自blog.csdn.net/2301_76161469/article/details/131684668
今日推荐