问题1:为什么要内存对齐?

  • 平台原因:不是所有的平台都能访问到任意地址上的任何数据,如果在特定的地址上找不到数据的话就会抛出硬件异常。
  • 性能问题:简单的来说如果没有使用内存对齐的话,相对于内存对齐,CPU要更多次去访问内存才能将数据正确的读出,所以会出现性能上的降低。(甚至有些CPU没有采取内存对齐的话就会罢工)

问题2:内存对齐有什么规则/规律?

  • 第一条规则:第一个数据成员一定要放在偏移量(offset)为0的地址
  • 第二条规则:VS下用#progma pack(n)用来设置内存对齐的系数,每次将要对齐的数据成员长度和n来比较,小的那个一个作为标准来对齐。
  • 第三条规则:将所有数据成员对齐之后,整个class或者struct也要进行对齐,它的大小必须是这个类中所占字节最大的数据成员的字节的整数倍数
  • -


问题3:如何来理解这三条规则?

接下来我将使用几个例子来详细解释内存对齐的三条规则是怎么使用的。

例子1:

#include<iostream>
using namespace std;
class A
{
char a;//1个字节
int b;//4个字节
char c;//1个字节
};
int main()
{
cout << sizeof(A) << endl;//输出的结果是12个字节
}

这是内存分配的示意图:

我们来将代码一步一步分析:

class A
{
char a;//char 1个字节大小
//根据第一条规则,第一个数据成员应该放在第一个位置,所以a从0开始 int b;//4个字节
//根据第二条规则:因为在VS下n默认是8,int在32位下为4个字节,4小于8,所以我们要以4来对齐,而不是8。
//要怎么对齐呢?放在a的后一个位置2可以吗?肯定是不行的,因为我们要以4来对齐,所以它能放的位置必须要以4的倍数开头,比如0,4,8。所以它不能放在成员a的后面,否则的话它就是以2开头了,而2并不是4的整数倍(这里是重点!!!)
//所以b的位置放在4开始 char c;//1个字节
//根据第二条规则:char为1个字节,小于8,所以要以1为对齐系数。
//这时候成员c的起始位置必须以1的倍数为开始,所以可以放在成员b的后面。
//c就是从8开始 //使用规则3:
//一直到了这一步,成员的对齐已经完成了,一共占用了9个字符。接下来要将整个class对齐,我们需要将整个class的大小设置为int的整数倍数,所以9%4=1,我们需要扩展为12个字符才完全对齐。
//到这一步就完全完成了,我们可以参照上面的内存图,如果还不清楚的话可以从头再梳理一遍,相信很快就能完全理解这个规则。
};

例子2:



代码:

#include<iostream>
using namespace std;
class B
{
double a;//8个字符
char b;//1个字符
int c;//4个字符
};
int main()
{
cout << sizeof(B) << endl;
}

内存布局:



我们来将代码一步一步分析:

#include<iostream>
using namespace std;
class B
{
double a;//8个字符
//使用第一条规则:
//第一个成员应该从第一个位置开始放置,也就是地址0 char b;//1个字符
//第二条规则:char1个字符,比8小,所以我们以1为对齐系数
//b的起始位置必须是1的倍数,所以紧跟着double的后面存放 int c;//4个字符
//第二条规则:int4个字节小于8,所以以4为对齐系数。
//c的起始位置必须是4的倍数,所以不能跟着b的后面存放,因为9不是4的倍数,所以我们必须以12为起始地址,因为12是4的倍数。
//这时候已经占了16个字符 //第三条规则
//class的大小要是double的整数倍(因为double所占字符最大),因为16个字符已经是8的倍数,所以不需要再进行内存对齐。
//如果有不清楚的,可以从上面的规则开始重新看起。
};
int main()
{
cout << sizeof(B) << endl;
}

总结:用progma pack(n)可以强制设置你想要的内存对齐的比较系数,如果你设置为1的话,就是所有的成员都紧凑的贴在一起,不会有空隙,而如果n设置为16,比所有的数据成员的字符大小都大,那么永远都不会以n为对齐系数。

如果还有不懂的地方,可以交流一下。

[C++]我的理解之内存对齐的更多相关文章

  1. C语言中内存对齐

    今天一考研同学问我一个问题,一个结构体有一个int类型成员和一个char类型成员,问我这个结构体类型占多少个字节,我直接编个程序给他看结果.这个结构体占八个字节,咦,当时我蛮纳闷的,一个int类型四个 ...

  2. 为什么要内存对齐 Data alignment: Straighten up and fly right

    转载于http://blog.csdn.net/lgouc/article/details/8235471 为了速度和正确性,请对齐你的数据. 概述:对于所有直接操作内存的程序员来说,数据对齐都是很重 ...

  3. 深入理解c/c++ 内存对齐

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

  4. c/c++中内存对齐完全理解

    一,什么是内存对齐?内存对齐用来做什么? 所谓内存对齐,是为了让内存存取更有效率而采用的一种编译阶段优化内存存取的手段. 比如对于int x;(这里假设sizeof(int)==4),因为cpu对内存 ...

  5. C/C++中内存对齐问题的一些理解(转)

    内存对齐指令 一般来说,内存对齐过程对coding者来说是透明的,是由编译器控制完成的 如对内存对齐有明确要求,可用#pragma pack(n)指定,以n和结构体中最长数据成员长度中较小者为有效值 ...

  6. C/C++: C++位域和内存对齐问题

    1. 位域: 1. 在C中,位域可以写成这样(注:位域的数据类型一律用无符号的,纪律性). struct bitmap { unsigned a : ; unsigned b : ; unsigned ...

  7. (转)CPU Cache与内存对齐

    转自:http://blog.csdn.net/zhang_shuai_2011/article/details/38119657 原文如下: 一. CacheCache一般来说,需要关心以下几个方面 ...

  8. 内存对齐 和 sizeof小结

    数据对齐(内存对齐)指该数据所在的地址必须是该数据长度的整数倍.X86CPU能直接访问对齐的数据,当它试图访问未对齐的数据时,会在内部进行一系列的调整,降低运行速度.数据对齐一般出现在结构体和类中,在 ...

  9. 解析C语言结构体对齐(内存对齐问题)

    C语言结构体对齐也是老生常谈的话题了.基本上是面试题的必考题.内容虽然很基础,但一不小心就会弄错.写出一个struct,然后sizeof,你会不会经常对结果感到奇怪?sizeof的结果往往都比你声明的 ...

  10. C语言再学习之内存对齐

    昨天看Q3的代码,看到有个_INTSAIZEOF的宏,着实晕了一阵.一番google后,终于明白,这个宏的作用是求出变量占用内存空间的大小,先看看_INTSAIZEOF的定义吧: #define _I ...

随机推荐

  1. 一键体验 Istio

    背景介绍 Istio 是一种服务网格,是一种现代化的服务网络层,它提供了一种透明.独立于语言的方法,以灵活且轻松地实现应用网络功能自动化.它是一种管理构成云原生应用的不同微服务的常用解决方案.Isti ...

  2. 齐博X1数据表之系统参数

    https://v.youku.com/v_show/id_XMzg0MTEzMzEyOA== 不会插入视频 直接发 优酷地址吧= =!

  3. 某Hi3516EV300摄像头折腾笔记

    最近因工作需要买了某款HI3516DV300开发板,但是价格死贵,于是在国内某著名电商网站上瞎逛,很巧发现一家店铺买摄像头模组,主控HI3516EV300,cmos是IMX335,价格不到200元,然 ...

  4. 图文详解丨iOS App上架全流程及审核避坑指南

    App Store作为苹果官方的应用商店,审核严格周期长一直让用户头疼不已,很多app都"死"在了审核这一关,那我们就要放弃iOS用户了吗?当然不是!本期我们从iOS app上架流 ...

  5. 扫雷(哈希+bfs)

    扫雷 题目描述: 小明最近迷上了一款名为<扫雷>的游戏. 其中有一个关卡的任务如下: 在一个二维平面上放置着 n 个炸雷,第 i 个炸雷 (x\(_i\),y\(_i\),r\(_i\)) ...

  6. Oracle部署,关于日志文件系统选择(硬盘格式化、挂载)

    之前部署过好多Oracle服务,采用的日志文件系统一直是ext3.但是我观察到很多人在格式化/挂载数据盘时,采用的日志文件系统类型有ext3.ext4.xfs等,这不禁让我发出疑问,哪个类型的数据处理 ...

  7. 常用到的read命令

    记录一下. 几个简单参数介绍 read -p :显示提示信息 read -s :静默模式(Silent mode),不会在屏幕上显示输入的字符.当输入密码和其它确认信息的时候,这是很有必要的. rea ...

  8. 嵌入式-C语言基础:指针偏移打印数组

    在C语言中,数组名代表数组中首元素的地址,所以,下面两句获取数组的首地址是等价的: #include<stdio.h> int main() { int a[5]={1,2,3,4,5}; ...

  9. Quartz的使用

    Quartz的使用 可以下载该项目进行测试查看:https://gitee.com/zhou-jiahao/quartz_demoq 1 初始Quartz 如果你的定时任务没有分布式需求,但需要对任务 ...

  10. 2022-11-10 Acwing每日一题

    本系列所有题目均为Acwing课的内容,发表博客既是为了学习总结,加深自己的印象,同时也是为了以后回过头来看时,不会感叹虚度光阴罢了,因此如果出现错误,欢迎大家能够指出错误,我会认真改正的.同时也希望 ...