(转)内存对齐全攻略--一、不涉及…

本文详细解析了内存对齐的基本原则,包括不涉及位域的内存对齐、涉及位域的内存对齐、成员变量含有结构体的内存对齐情况以及内存对齐的原因和优点。通过具体实例展示了内存对齐如何影响结构体的大小。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

主要讨论四点:
一、不涉及位域的内存对齐原则
二、涉及位域的内存对其原则
三、成员变量含有结构体的内存对齐情况
四、要求内存对齐的原因及优点

引子:

 1#include <iostream>
 2using namespace std;
 3struct A
 4{
    char m;
    int n;
 7};
 8int main ()
 9{
10    A a;
11    a.m=1;a.n=2;
12    printf("sizeof(A)=%d\nsizeof(A.m)=%d\nsizeof(A.n)=%d\n",sizeof(a),sizeof(a.m),sizeof(a.n));
13    return 0;
14}
预测输出:
sizeof(A)=5
sizeof(A.m)=1
sizeof(A.n)=4
实际输出:

(转)内存对齐全攻略--一、不涉及位域的内存对齐原则

 

分析:
也许该疑问了,sizeof(A.m)=1,sizeof(A.n)=4,sizeof(A)不是该1+4=5吗,怎么是8呢?

这是因为程序员眼中的内存与处理机处理内存的不一致,程序员通常认为内存就是一些列简单的字节数组,在C语言以及它的衍生语言中,char*被普遍认为代表一块内存区域,即使是Java也用byte[]来代表原始内存如下图所示:

(转)内存对齐全攻略--一、不涉及位域的内存对齐原则

 

处理机在对内存进行存取操作时,却不是以单个字节为单位来进行的,它通常是以2 、4、 8 、16大小的字节块来进行的。我们称处理器访问内存时一次存取的内存大小为“内存访问粒度”,如下图所示:

(转)内存对齐全攻略--一、不涉及位域的内存对齐原则

 

可以看一下内存中的情况,确实是8个字节:

(转)内存对齐全攻略--一、不涉及位域的内存对齐原则


一、不涉及位域的内存对齐原则
规则如下,然后来举例说明:
1) 对结构的数据成员,第一个数据成员位于偏移为0的位置,以后每个数据成员的偏移量必须是MIN(#pragma pack()指定的数,此数据成员的自身长度) 的倍数,我们称MIN(#pragma pack()指定的数,此数据成员的自身长度) 为该结构成员的对齐模数。
注:程序中通常是不指定#pragma pack()它的,默认值为8,从哪里可以看到呢,看下图(发现用图说话有时是直观方便易懂……):

(转)内存对齐全攻略--一、不涉及位域的内存对齐原则

2)为结构体的一个成员开辟空间之前,编译器首先检查预开辟空间的首地址相对于结构体首地址的偏移是否是本成员的整数倍,若是,则存放本成员,反之,则在本成员和上一个成员之间填充一定的字节(填充字节为CC,也就是int3中断),以达到整数倍的要求,也就是将预开辟空间的首地址后移几个字节。


3)在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,对齐将按照MIN(指定的#pragma pack()的数值,MAX(结构(或联合)数据成员长度))进行对齐。

这部分以这段代码为例:

 1#include <iostream>
 2using namespace std;
 3struct A
 4{
    char c;
    int i;
    short s;
 8};
 9int main ()
10{
11    A a;
12    a.c=1;a.i=2;a.s=3;
13    printf("sizeof(A)=%d\n",sizeof(A));
14    return 0;
15}

这里,我们采用系统默认的#pragma pack(8),则
c 的对齐模数为:MIN(sizeof(char),8)=MIN(1,8)=1
的对齐模数为:MIN(sizeof(int),8)=MIN(4,8)=4
s 的对齐模数为:MIN(sizeof(short),8)=MIN(2,8)=2
根据规则一:

 

(转)内存对齐全攻略--一、不涉及位域的内存对齐原则

根据规则二:
当给c开辟空间以后,为i开辟空间之前,编译器先检查与开辟空间的首地址,发现为1,不是i的对齐模数的整数倍,则向后找,一直到地址4时,以4为起始,向后开辟四个字节大小的空间,而之前的1,2,3这三处则填充 CC ,如下图:
(转)内存对齐全攻略--一、不涉及位域的内存对齐原则

根据规则三:
现在进行结构体对齐,整个sizeof(A)=10,而MIN(8,MAX(sizeof(c),sizeof(i),sizeof(s)))=4,则 sizeof(A)=MIN(4N),并且sizeof(A)>=10,故,sizeof(A)=12.再将10,11空间给填充上CC:
(转)内存对齐全攻略--一、不涉及位域的内存对齐原则

要知道为什么有的是CC,有的是00啊,还有,千万别看到sizeof(A)=12,就把12位置也给填上CC啊

这里贴上运行结果,果然跟分析一致啊,呵呵,不一致就怪了~
(转)内存对齐全攻略--一、不涉及位域的内存对齐原则

 

原文来自:雨枫技术教程网 http://www.fengfly.com
原文网址:http://www.fengfly.com/plus/view-173129-1.html

 











 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值