问题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. HNOI2008GT考试

    题目链接 考虑dp,f(i,j)表示做到了第i位(共n位),当前的后缀串与A1~Aj相匹配 接下来的方案数.转移的话枚举一个k=0~9表示这位选什么,如果选了以后,匹配的位置会改变到 j' ,j'可以 ...

  2. redis 分布式锁 PHP

    redis分布式 1.redis是单线程操作 2.分布式会出现的问题,死锁 3.redis分布式(集群).多台服务器里面都有多个单机redis.然后这些redis之间相互链接.还有查看各个单台服务器之 ...

  3. Ansible 批处理实战

    软件简介 Ansible 是一款自动化运维工具,基于 Python 开发,集合了众多运维工具(puppet.chef.func.fabric)的优点,实现了批量系统配置.批量程序部署.批量运行命令等功 ...

  4. Springboot 一行代码实现文件上传 20个平台!少写代码到极致

    大家好,我是小富~ 技术交流,公众号:程序员小富 又是做好人好事的一天,有个小可爱私下问我有没有好用的springboot文件上传工具,这不巧了嘛,正好我私藏了一个好东西,顺便给小伙伴们也分享一下,d ...

  5. C#-多线程的使用Tread

    首先是概念,什么是线程? 线程是操作系统分配CPU时间的基本单元,在一个进程中可以有多个线程同时执行代码. 谈一谈什么是进程? 简单的说,一个正在运行的应用程序可以视为一个进程,进程间相互独立,资源不 ...

  6. 【原创】i.MXRT J-Flash烧写算法使能eFuse熔丝位写入

    ​       临近年底,终于又憋了一篇文章出来,本来年初的时候是有计划把去年总结的一些东西整理下发布出来的,结果还是被工作和生活上各种琐事给耽搁了.哎,今年刚过了自己35岁的生日,眼瞅着这个人生节点 ...

  7. element-plus 消息提示

    用来显示「成功.警告.消息.错误」类的操作 <template> <el-button :plain="true" @click="open2" ...

  8. 👍SpringSecurity单体项目最佳实践

    SpringSecurity单体项目最佳实践 到这里,我们的SpringSecurity就已经完结啦,文章中可能有些地方不能做到全面覆盖,视频教程地址 初始项目地址 完成项目地址 1.搭建环境 建议下 ...

  9. MQTT GUI 客户端 可视化管理工具推荐

    一款好用的 MQTT 客户端工具可以极大地提高开发者使用MQTT的效率.MQTT 客户端工具常用于建立与 MQTT 服务器的连接,进行主题订阅.消息收发等操作. 今天,在此推荐一款优秀的MQTT GU ...

  10. 如何把Java代码玩出花?JVM Sandbox入门教程与原理浅谈

    在日常业务代码开发中,我们经常接触到AOP,比如熟知的Spring AOP.我们用它来做业务切面,比如登录校验,日志记录,性能监控,全局过滤器等.但Spring AOP有一个局限性,并不是所有的类都托 ...