当前位置:首页 > 芯闻号 > 充电吧
[导读]内存对齐问题是各种开发类面试中最热门的问题,面试管一般认为这个问题可以考察被面试者对内存细节的了解情况,确实这个问题对于C++初学者来说是个十足的难题因为它不仅涉及了pragma pack(n) 设定

内存对齐问题是各种开发类面试中最热门的问题,面试管一般认为这个问题可以考察被面试者对内存细节的了解情况,确实这个问题对于C++初学者来说是个十足的难题因为它不仅涉及了pragma pack(n) 设定的内存对齐系数还涉及了相关内存分配的细节。


内存对齐:

我们知道现代计算机体系中CPU按照双字、字、字节访问存储内存,并通过总线进行传输,若未经一定规则的对齐,CPU的访址操作与总线的传输操作将会异常的复杂,所以现代编译器中都会对内存进行自动的对齐。

1.内存对齐系数

说道内存对齐,就不得不说内存对齐系数, 对齐系数最简单的设置方法是使用 #pragma pack(n)进行设置,这部分点进链接在我的文章内有详细说明!

2.sizeof

说到内存对齐第二个不得不说的就是sizeof,它的基本作用是判断数据类型或者表达式长度,要注意的是这不是一个函数,而是一个C++中的关键字!字节数的计算在程序编译时进行,而不是在程序执行的过程中才计算出来!

3.类型的长度与数据成员对齐

你的计算机中,数据类型的长度指的就是在你的计算机中对数据类型使用sizeof得到的结果,当然这个在各种不同的编译环境下得到的结果是不同的。
比如在32位Visual Studio环境下:
cout << sizeof(char) << endl;  // 1
cout << sizeof(short) << endl;  // 2
cout << sizeof(int) << endl;  // 4
cout << sizeof(long) << endl;  // 4

cout << sizeof(double) << endl;  // 8


而在64位G++编译环境下:
cout << sizeof(char) << endl;  // 1
cout << sizeof(short) << endl;  // 2
cout << sizeof(int) << endl;  // 4
cout << sizeof(long) << endl;  // 8

cout << sizeof(double) << endl;  // 8

下面我将在32位Visual Studio环境下讲解数据成员对齐:
首先我们要清楚结构体struct中的成员在内存中的分配是连续的,struct内的首地址也就是struct内第一个数据成员的地址,换句话说struct内第一个数据成员离struct开始的距离offset = 0。
数据成员对齐的规则就是,而在第一个成员之后,每个成员距离struct首地址的距离 offset, 都是struct内成员自身长度(sizeof) 与 #pragma pack(n)中的n的最小值的整数倍,如果未经对齐时不满足这个规则,在对齐时就会在这个成员前填充空子节以使其达到数据成员对齐。

默认n为8时:

#pragma pack(8)

struct {
    char a;
    double b;
} myStruct;
cout << sizeof myStruct << endl;  // 16
cout << (int *)&myStruct.a << endl;  // 0024F898

cout << &myStruct.b << endl;  // 0024F8A0(因运行时而异)


当设置n为4也就是min(sizeof(double), n) = 4 时:
#pragma pack(4)
struct {
    char a;
    double b;
} myStruct;
cout << sizeof myStruct << endl; // 12
cout << (int *)&myStruct.a << endl; // 0046F76C
cout << &myStruct.b << endl; // 0046F770
第一个例子时,最小值为8,填充7个字节到char a 之后。

第二个例子时,最小值为4,填充3个字节到char a之后。

4.整体对齐

编译器在进行过数据成员对齐之后,还要进行整体对齐。与数据对齐相似但不是完全相同, 如果数据对齐完成时struct的大小不是 struct内成员自身长度最大值(sizeof) 与 #pragma pack(n)中的n的最小值的整数倍。(注意这里是成员中长度最大的那个与n比较,而不是特定的一个成员。)就要在struct的最后添加空字节直到对齐。
当设置n为4也就是min(sizeof(short), n) = 2 时:
#pragma pack(4)
struct {
    char a;
    short b;
    char c;
} myStruct;
cout << sizeof myStruct << endl;  // 6
cout << (int *)&myStruct.a << endl;  // 003DFED0
cout << &myStruct.b << endl;  // 003DFED2
cout << (int *)&myStruct.c << endl;  // 003DFED4
在上面的例子中,char a offset为0 因成员对齐占据[D0]填充[D1]共两个字节,short b是最大长度成员无需对齐占据[D2-D3]两个字节,它的offset是2,而char c的offset是4占据[D4]无需成员对齐,但此时struct的大小是2+2+1 = 5字节,不是2的整数倍,所以我们要填充空子节在最后直到struct大小达到2的整数倍,这就是整体对齐。
经过了数据成员对齐与整体对齐之后内存对齐就完成了,如果深入思考上述规则还会发现:即使是同样数目与数量的数据成员,在摆放的顺序不同时struct的大小也会不同,下面就是一个例子:
这样摆放是12字节:


摆放方式改变时结果确变成了8字节:


由于这种特性,如果在网络编程或相关内存操作时如果不加以注意的话,就会造成隐秘而难以纠正的错误,请大家务必小心!



本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

9月2日消息,不造车的华为或将催生出更大的独角兽公司,随着阿维塔和赛力斯的入局,华为引望愈发显得引人瞩目。

关键字: 阿维塔 塞力斯 华为

加利福尼亚州圣克拉拉县2024年8月30日 /美通社/ -- 数字化转型技术解决方案公司Trianz今天宣布,该公司与Amazon Web Services (AWS)签订了...

关键字: AWS AN BSP 数字化

伦敦2024年8月29日 /美通社/ -- 英国汽车技术公司SODA.Auto推出其旗舰产品SODA V,这是全球首款涵盖汽车工程师从创意到认证的所有需求的工具,可用于创建软件定义汽车。 SODA V工具的开发耗时1.5...

关键字: 汽车 人工智能 智能驱动 BSP

北京2024年8月28日 /美通社/ -- 越来越多用户希望企业业务能7×24不间断运行,同时企业却面临越来越多业务中断的风险,如企业系统复杂性的增加,频繁的功能更新和发布等。如何确保业务连续性,提升韧性,成...

关键字: 亚马逊 解密 控制平面 BSP

8月30日消息,据媒体报道,腾讯和网易近期正在缩减他们对日本游戏市场的投资。

关键字: 腾讯 编码器 CPU

8月28日消息,今天上午,2024中国国际大数据产业博览会开幕式在贵阳举行,华为董事、质量流程IT总裁陶景文发表了演讲。

关键字: 华为 12nm EDA 半导体

8月28日消息,在2024中国国际大数据产业博览会上,华为常务董事、华为云CEO张平安发表演讲称,数字世界的话语权最终是由生态的繁荣决定的。

关键字: 华为 12nm 手机 卫星通信

要点: 有效应对环境变化,经营业绩稳中有升 落实提质增效举措,毛利润率延续升势 战略布局成效显著,战新业务引领增长 以科技创新为引领,提升企业核心竞争力 坚持高质量发展策略,塑强核心竞争优势...

关键字: 通信 BSP 电信运营商 数字经济

北京2024年8月27日 /美通社/ -- 8月21日,由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV2024超高清全产业链发展研讨会上宣布正式成立。 活动现场 NVI技术创新联...

关键字: VI 传输协议 音频 BSP

北京2024年8月27日 /美通社/ -- 在8月23日举办的2024年长三角生态绿色一体化发展示范区联合招商会上,软通动力信息技术(集团)股份有限公司(以下简称"软通动力")与长三角投资(上海)有限...

关键字: BSP 信息技术
关闭
关闭