结构体「内存对齐」

具体作用:用于计算结构所占内存的大小,格式如下sizeof(struct xxx)

为什么需要结构体内存对齐?

1.平台原因:不是所有平台都可以任意访问地址上的任意数据,某些硬件平台只可以访问某些地址处的特定类型数据

2.性能原因:尽可能在自然边界上对齐,访问未对齐的内存,处理器要访问两次,而对齐的内存访问一次即可

结构体内存对齐规则

1.第一个成员在结构体变量偏移量为0处的地址

2.第二个成员开始,每个成员都要分别对齐到各自对齐数的整数倍数处

3.结构体总大小:所有成员的对齐数中最大对齐数的整数倍

4.如果结构体中嵌套结构体成员,要将嵌套结构体的成员对齐到自己的最大对齐数的整数倍处

1.第一个成员在结构体变量偏移量为0处的地址

假设将内存可视化,起始地址标为0,那么123依次排列

2.第二个成员开始,每个成员都要分别对齐到各自对齐数的整数倍数处

对齐数:结构体成员自身大小和默认对齐数的较小值

Visual Studio默认对齐数:8

例如:char类型用1与8比较取1

int类型用4与8比较取4

double类型取8

linux/gcc:没有默认对齐数,对齐数为成员自身大小

3.结构体总大小:所有成员的对齐数中最大对齐数的整数倍

4.如果结构体中嵌套结构体成员,要将嵌套结构体的成员对齐到自己的最大对齐数的整数倍处,结构体的总大小为最大对齐数(包含嵌套结构体的对齐数)的整数倍(结合例4理解)

结合实例具体分析:

例1:

//结构体内存对齐
struct S1
{
	char a;
	int b;
	char c;
	
};

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

分别有abc这三个成员,其所占内存大小分别为1,4,1 但不可将结构体大小简单理解为三者相加

按照步骤:

1.将a排序在0起始位置处。

2.排布b,int类型的对齐数为4,所有会在4的倍数处排布,因此会浪费123这三个字节的大小。

3.c为char类型可以接在b之后。

4.观察所有成员的类型,发现int为最大,所以按照补全的思想,使其结构体总内存大小为所有成员的对齐数中最大对齐数的整数倍,得到结果为12

例2:

//结构体内存对齐

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

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

跟例1 相似,

1.排布好a在0位置处

2.此时b的类型为char,内存对齐数为1,所以可以排布在1的倍数处(任意位置)

3.c为int类型,从4号位置开始排布

4.综合计算,总共占据内存大小为8字节

 例3:

//结构体内存对齐

struct S3
{
	double a;
	char b;
	int c;
};

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

相同的思路,只不过此时多出了一个double类型:

1.double类型占据内存大小为8字节

2.char类型的b随意排布在8地址处

3.c为int类型,因此按顺序排在下一个4的倍数12处

4.因为最大的数据类型为double,所以结构体内存大小为8的倍数16

 例4:

//结构体内存对齐
struct S3
{
	double a;
	char b;
	int c;
};
struct S4
{
	char d;
	struct S3 s3;
	double e;
};


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

S4中嵌套了一个结构体S3:

1.先排好char d,

2.嵌套结构体的成员对齐到自己(嵌套结构体成员)的最大对齐数的整数倍处

回顾S3中结构体成员分别为double,char ,int类型,所以对齐数为:8,所以占据8-23号共16字节

3.排布最后一个e,类型为double

4.观察所有的结构体成员(包括嵌套成员的结构体中的成员),最终占据内存大小为最大对齐数的整数倍

修改默认对齐数:

#pragma pack(1)//设置默认对齐数为1
struct S1
{
	char a;
	int b;
	char c;
	
};
#pragma ()//解除,取消设置的默认对齐数,还原为默认

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值