[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 ...
随机推荐
- 去除router-link中的下划线
文章目录 1.设置router-link的样式 2.效果展示 1.设置router-link的样式 text-decoration: none; 2.效果展示
- IDEA中设置背景图片(超详细)
文章目录 1.效果图 2.详细设置过程 1.效果图 2.详细设置过程
- photoshop 2021 for mac安装教程,亲测可用!!!
小编分享下photoshop cc 2021 for mac 安装教程,适配M1芯片,让大家完美使用ps2021,畅享所有新功能Adobe Photoshop2021(简称PS) 新版本主要增加了Ne ...
- 基于mnist的P-R曲线(准确率,召回率)
一.准确率,召回率 TP(True Positive):正确的正例,一个实例是正类并且也被判定成正类 FN(False Negative):错误的反例,漏报,本为正类但判定为假类 FP(False P ...
- Xpath 高级用法
xpath 高级用法 1. 匹配当前节点下的所有: .// . 表示当前 // 表示当前标签下的所有标签 注: 要配合使用 2. 匹配某标签的属性值: /@属性名称 这里以input里的value值为 ...
- 记一次HTTPClient模拟登录获取Cookie的开发历程
记一次HTTPClient模拟登录获取Cookie的开发历程 环境: springboot : 2.7 jdk: 1.8 httpClient : 4.5.13 设计方案 通过新建一个 ...
- 支持JDK19虚拟线程的web框架之四:看源码,了解quarkus如何支持虚拟线程
欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 前文链接 支持JDK19虚拟线程的web框架,之一:体 ...
- vue3中的defineProps,watch,computed
在vue3的setup语法糖中,defineProps不需要引入了 <script setup> import { computed } from '@vue/reactivity'; i ...
- Pthread 并发编程(二)——自底向上深入理解线程
Pthread 并发编程(二)--自底向上深入理解线程 前言 在本篇文章当中主要给大家介绍线程最基本的组成元素,以及在 pthread 当中给我们提供的一些线程的基本机制,因为很多语言的线程机制就是建 ...
- 渗透技巧基于Swagger-UI的XSS
目录 免责声明: 漏洞简述: 漏洞实现 POC 漏洞利用 如何大规模找到 Swagger UI Google FOFA XRAY 修复 免责声明: 本文章仅供学习和研究使用,严禁使用该文章内容对互 ...