[C++]我的理解之内存对齐
问题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++]我的理解之内存对齐的更多相关文章
- C语言中内存对齐
今天一考研同学问我一个问题,一个结构体有一个int类型成员和一个char类型成员,问我这个结构体类型占多少个字节,我直接编个程序给他看结果.这个结构体占八个字节,咦,当时我蛮纳闷的,一个int类型四个 ...
- 为什么要内存对齐 Data alignment: Straighten up and fly right
转载于http://blog.csdn.net/lgouc/article/details/8235471 为了速度和正确性,请对齐你的数据. 概述:对于所有直接操作内存的程序员来说,数据对齐都是很重 ...
- 深入理解c/c++ 内存对齐
内存对齐,memory alignment.为了提高程序的性能,数据结构(尤其是栈)应该尽可能地在自然边界上对齐.原因在于,为了访问未对齐的内存,处理器需要作两次内存访问:然而,对齐的内存访问仅需要一 ...
- c/c++中内存对齐完全理解
一,什么是内存对齐?内存对齐用来做什么? 所谓内存对齐,是为了让内存存取更有效率而采用的一种编译阶段优化内存存取的手段. 比如对于int x;(这里假设sizeof(int)==4),因为cpu对内存 ...
- C/C++中内存对齐问题的一些理解(转)
内存对齐指令 一般来说,内存对齐过程对coding者来说是透明的,是由编译器控制完成的 如对内存对齐有明确要求,可用#pragma pack(n)指定,以n和结构体中最长数据成员长度中较小者为有效值 ...
- C/C++: C++位域和内存对齐问题
1. 位域: 1. 在C中,位域可以写成这样(注:位域的数据类型一律用无符号的,纪律性). struct bitmap { unsigned a : ; unsigned b : ; unsigned ...
- (转)CPU Cache与内存对齐
转自:http://blog.csdn.net/zhang_shuai_2011/article/details/38119657 原文如下: 一. CacheCache一般来说,需要关心以下几个方面 ...
- 内存对齐 和 sizeof小结
数据对齐(内存对齐)指该数据所在的地址必须是该数据长度的整数倍.X86CPU能直接访问对齐的数据,当它试图访问未对齐的数据时,会在内部进行一系列的调整,降低运行速度.数据对齐一般出现在结构体和类中,在 ...
- 解析C语言结构体对齐(内存对齐问题)
C语言结构体对齐也是老生常谈的话题了.基本上是面试题的必考题.内容虽然很基础,但一不小心就会弄错.写出一个struct,然后sizeof,你会不会经常对结果感到奇怪?sizeof的结果往往都比你声明的 ...
- C语言再学习之内存对齐
昨天看Q3的代码,看到有个_INTSAIZEOF的宏,着实晕了一阵.一番google后,终于明白,这个宏的作用是求出变量占用内存空间的大小,先看看_INTSAIZEOF的定义吧: #define _I ...
随机推荐
- 通过URL保存文件
1 <?php 2 3 function dlfile($file_url, $save_to) 4 { 5 $content = file_get_contents($file_url); 6 ...
- 一天十道Java面试题----第五天(spring的事务传播机制------>mybatis的优缺点)
这里是参考B站上的大佬做的面试题笔记.大家也可以去看视频讲解!!! 文章目录 41.spring的事务传播机制 42 .spring事务什么时候会失效 43 .什么的是bean的自动装配.有哪些方式? ...
- 使用 Windows Core Audio APs 进行 Loopback Recording 并生成 WAV 文件
参考文档 COM Coding Practices Audio File Format Specifications Core Audio APIs Loopback Recording #inclu ...
- 微信抢红包小技巧(python模拟100万次)
之前,在网上看到一篇文章,说多人抢红包时,微信红包金额的分配规则是0.01元到当前剩余金额平均数的2倍(最后一个人金额为当前剩下的所有金额),所以写了一个python程序,模拟量一百万次,分析了一下抢 ...
- k8s集权IP更换
-.背景描述 背景:在场内进行部署完成后标准版产品,打包服务器到客户现场后服务不能正常使用,因为客户现场的IP地址不能再使用场内的IP,导致部署完的产品环境在客户现场无法使用:此方案就是针对这一问题撰 ...
- 你给文字描述,AI艺术作画,精美无比!附源码,快来试试!
作者:韩信子@ShowMeAI 深度学习实战系列:https://www.showmeai.tech/tutorials/42 TensorFlow 实战系列:https://www.showmeai ...
- Fidder 抓包工具
fiddler抓包原理 如上图本文一些 不重要 的鸡肋功能 自行百度 1. 安装与配置 1. 安装 安装地址https://www.telerik.com/download/fiddler可能有点慢 ...
- python基础类型,字符串
python基本类型小结 # str,可以用索引取值,但是不能通过索引改变值, # a = "123" a[0]=10,直接TypeError因为字符串是不可变类型 # list, ...
- JVM学习笔记——内存模型篇
JVM学习笔记--内存模型篇 在本系列内容中我们会对JVM做一个系统的学习,本片将会介绍JVM的内存模型部分 我们会分为以下几部分进行介绍: 内存模型 乐观锁与悲观锁 synchronized优化 内 ...
- Kubernetes集群YAML文件详解
Kubernetes集群YAML文件详解 概述 k8s 集群中对资源管理和资源对象编排部署都可以通过声明样式(YAML)文件来解决,也就是可以把需要对资源对象操作编辑到YAML 格式文件中,我们把这种 ...