C语言内存对齐

软件发布|下载排行|最新软件

当前位置:首页IT学院IT技术

C语言内存对齐

Hero 2021   2022-09-08 我要评论

结构体的内存对齐是一个特别热门的知识点!

引例

#include<iostream>
using namespace std;
struct S
{
	char c;		// 1
	int a;		// 4
	char d;		// 1
};
int main()
{
	struct S s = { 'a',2,'y'};
	cout << sizeof(struct S) << endl;// 12
	cout << sizeof(s) << endl; 		 // 12
	return 0;
}

结构体内存对齐规则

1. 结构体的第一个变量,永远放在结构体起始位置偏移量为0的地方。

2. 结构体成员从第二个成员开始,剩下的成员总是放在偏移量为一个对齐数的整数倍处。 对齐数=编译器默认的对齐数与变量自身大小的较小值(VS的默认对齐数是8,Linux没有默认对齐数)

3. 结构体的总大小,必须是结构体各个成员中最大对齐数的整数倍

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

满足第一点:

满足第二点:

满足第三步:

为了满足第三点,我们要内存对齐,结构体的总大小必须是4的倍数,现在只有12能够满足要求了。

但是我们存在着一些空间的浪费啊!

那么为什么要有内存对齐呢

大部分的参考资料都是如是说的:

平台原因(移植原因):

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

性能原因:

数据结构(尤其是栈)应该尽可能地在自然边界上对齐。 原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。

例如:某些场景下一次只能读取4byte空间:对比对齐和不对齐,可能读取数据就可能出错。

总体来说:

结构体的内存对齐是拿空间来换取时间的做法。

如何优化

 那在设计结构体的时候,我们既要满足对齐,又要节省空间,如何做到呢? 那就是让占用空间小的成员尽量集中在一起。

//例如:
struct S1
{
	char c1;
	int i;
	char c2;
};
struct S2
{
	char c1;
	char c2;
	int i;
};

S1和S2类型的成员一模一样,但是S1和S2所占空间的大小有了一些区别。

修改默认对齐数

#pragma修改默认对齐数

#include <stdio.h>
#pragma pack(8)//设置默认对齐数为8
struct S1
{
	char c1;
	int i;
	char c2;
};
#pragma pack()//取消设置的默认对齐数,还原为默认
#pragma pack(1)//设置默认对齐数为1
struct S2
{
	char c1;
	int i;
	char c2;
};
#pragma pack()//取消设置的默认对齐数,还原为默认
int main()
{
	//输出的结果是什么?
	printf("%d\n", sizeof(struct S1));
	printf("%d\n", sizeof(struct S2));
	return 0;
}

结论:

结构在对齐方式不合适的时候,我么可以自己更改默认对齐数。

Copyright 2022 版权所有 软件发布 访问手机版

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 联系我们