C++知识积累:内存对齐理解

2023-11-19

为什么要进行内存对齐?

       这是因为CPU的读取总是对齐的。举个例子,假设CPU是32位的,那么CPU每次读取的4字节数据的首地址都是4的倍数,也就是说,内存中数据首地址为4的倍数时,CPU一次操作就可以完成数据读取:

       假设有一个int型四字节大小的变量存放在0~3地址单元中,那么CPU只需要读取0~3这32位即可,而如果这个变量存放在2~5地址单元中,那么CPU就需要先取出0~3地址单元,去掉不需要的0~1,再取出4~7地址单元,去掉不需要的6~7,最后把剩下的2~3和4~5组合在一起才是需要的变量值,这样一来效率就降低了。

      换句话说,如果操作1字节的数据,可以是任意地址,如果是操作2字节的数据,如果开始地址在偶数地址,一次就可以取2字节,如果开始地址在奇数,就要2次内存操作才能完成;如果操作4字节的数据,最好开始地址在能被4整除的数值上,这样可以用一条32位的内存操作指令完成。

       也就是说,如果对齐了,可以提高读取效率。内存对齐是为了配合CPU更效率的进行数据读取,往往都是由编译器来完成:对于一般的变量(不仅仅是结构体变量和对象),都会让它们的首地址放在对齐边界上(在VS中可以看到,对于char型单字节大小的变量,其地址是任意的;对于short型双字节大小的变量,其地址只可能是偶数;而对于int型四字节大小的变量,其地址则只可能是4的倍数),而对于结构体成员和类的成员变量,也会把它们放到对齐边界上。

怎样进行内存对齐?

内存对齐原则:由数据成员本身大小以及#parama pack(n)的n值决定。有以下3个原则:
①第一个数据成员的偏移地址地址为最长数据成员长度的整数倍,即对齐长度为最长数据成员长度;(如果是含有虚函数的类,那么会在开头放置虚表指针,然后才是第一个数据成员)
②每一个数据成员相对于首地址的偏移量为该数据成员长度的整数倍,即对齐长度为该数据成员长度;(由于最长数据成员长度必定是每个数据成员长度的整数倍,因此②是兼容①的)
③所有数据成员对齐后,还要保证整个类/结构体/联合体的长度为最长数据成员长度的整数倍,即对齐长度为最长数据成员大小;

     如果设置了#pragma pack(n),那么这3个原则将取各自原对齐长度和n中的较小值作为对齐长度。

内存对齐举例

class A
{
	int x;
	char y;
	int z;
	double p;
	virtual void f();
};

       在类A中声明了一个虚函数,因此类A的开头会放置一个虚表指针,大小为4个字节,如果不对齐,那么第一个数据成员x的偏移量就为4,但是这样就违背了对齐原则①,因此会在虚表指针后补齐4个字节,让第一个数据成员x的首地址偏移为8,因此x就占据了8~11;

       此时第二个数据成员y的偏移就是12了,y的大小为1,因此是符合对齐原则的,y就占据了12;

       此时第三个数据成员z的偏移就是13了,z的大小为4,不符合对齐原则②,因此需要补齐3个字节,使得z的偏移量为16,z就占据了16~19;

       此时第四个数据成员p的偏移就是20了,p的大小为8,不符合对齐原则②,因此需要补齐4个字节,使得p的偏移量为20,p就占据了20~27;

       此时所有数据相对于首地址来说占据的内存地址为0~27,大小为28个字节,根据对齐原则③,类中最大数据成员大小为8,因此还需要在最后补齐4个字节,因此实际类占据的内存地址为0~31,大小为32个字节。

       关于此处的类A的内存分布可在VS-项目-属性-命令行中输入/d1 reportSingleClassLayoutA (查看全部分布情况用/d1 reportAllClassLayout),然后运行程序后查看,如图所示。

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++知识积累:内存对齐理解 的相关文章

  • C++_生成随机字符串

    include
  • Qt5实现与单片机ATS89S51通信

    Qt实现与单片机直接的通信上位机 单片机代码 测试环境 项目目标 实现效果 关键通信类 QSerialport 总结 这是我大二下学期的单片机课设做的一个小项目 实现上位机与下位机之间的通信 测试环境 开发环境 Qt5 96 Mingw32
  • 【C/C++】报错问题积累

    1 出现Deprecated declaration XXX give arg types c文件中 有没有参数的函数时 声明需要加void即 main c void fun main h void fun void
  • R语言学习笔记:分析学生的考试成绩

    孩子上初中时拿到过全年级一次考试所有科目的考试成绩表 正好可以用于R语言的统计分析学习 为了不泄漏孩子的姓名 就用学号代替了 感兴趣可以下载测试数据进行练习 num class chn math eng phy chem politics
  • [原]Pro*C介绍-内嵌SQL

    Translate by Z Jingwei Document address http www db stanford edu ullman fcdb oracle or proc html Pro C介绍内嵌SQL 概要 Pro C语法
  • android通过JNI用C/C++创建本地文件

    通过jni在本地创建文件 1 在android studio创建基本的jni工程 并且在APP界面成功显示 Hello from C 不会的可以看android studio使用jni 2 在native lib cpp文件中创建文件 为了
  • C语言pcre库的使用及验证IP地址的合法性

    PCRE是一个用C语言编写的正则表达式函数库 它十分易用 同时功能也很强大 性能超过了POSIX正则表达式库和一些经典的正则表达式库 在使用PCRE库时 首先肯定是需要安装pcre的 不过一般的系统都会有自带的PCRE库 不过如果想使用最新
  • Vc/MFC中自定义消息及其PostMessage触发使用

    http blog csdn net ztz0223 article details 2058402 http blog csdn net a8082649 article details 7733527 http bbs csdn net
  • c/c++入门教程 - 1.基础c/c++ - 1.0 Visual Studio 2019安装环境搭建

    推荐视频课程 https www bilibili com video BV1et411b73Z p 2 已投币三连 b站果然是个学习的网站 本来是想在linux环境下运行QT 于是先学了几个月linux嵌入式驱动开发 后来发现太底层了 与
  • JNA模拟复杂的C类型——Java映射char*、int*、float*、double*

    文章目录 引言 Java Native Type Conversions Java和C基本类型指针对应关系 Pointer的具体用法 引言 最近项目在用Java调用C写的一些三方库 没办法直接调 用Java封装一下C的接口 这就少不了要用到
  • 写时拷贝技术(copy-on-write)

    传统的fork 系统调用直接把所有的资源复制给新创建的进程 这种实现过于简单并且效率低下 因为它拷贝的数据也许并不共享 更糟的情况是 如果新进程打算立即执行一个新的映像 那么所有的拷贝都将前功尽弃 Linux的fork 使用写时拷贝 cop
  • 使用QZXing生成并解析二维码

    QZxing 是对 zxing 的一个封装 用于在 Qt 程序中加入条形码和二维码识别的功能 这里就讲讲如何编译和使用这个库 前几年 QZXing 的代码是放到 sourceforge net 上的 现在迁移到了 github com 所以
  • 如何学好C语言的数据结构与算法?

    C语言的数据结构与算法 难就难在链表 学会了链表 可能后面就一点都不难了 书籍推荐 数据结构与算法分析 C语言描述版 要深入学习的话可以选择这本书 因为针对链表的讲解是比较详细的 所以可以很快理解链表 跟着书上一点点实现基本操作 增删改查
  • GDAL多光谱与全色图像融合简单使用

    目录 简述 C 代码 效果对比 GDAL融合效果和原始多光谱波段对比 GDAL融合效果和原始全色波段对比 ARCGIS融合效果与原始全色和多光谱对比 GDAL融合效果与ArcGIS融合效果对比 简述 最近在GDAL的代码中看见了gdalpa
  • mfc窗口创建的create与oncreate

    在view类中 create 是虚函数由框架调用 是用来 生成一个窗口的子窗口 oncreate 消息响应函数 是用来 表示一个窗口正在生成 某个CWnd的Create函数由当前CWnd的Owner调用 而在CWnd Create中 又会调
  • Public Private Protect Inheritance and access specifiers

    In the previous lessons on inheritance we ve been making all of our data members public in order to simplify the example
  • stat 函数解析

    stat 函数的简单使用 stat 函数是用来获取文件的各种属性的一个linux下的常用API函数 函数原型为int stat const char path struct stat buf stat定义如下 struct stat dev
  • C/C++编程:令人印象深刻的高级技巧案例

    C C 编程语言在软件开发领域有着悠久的历史 由于其高效 灵活和底层访问能力 至今仍然被广泛应用 本文将介绍一些在C C 编程中令人印象深刻的高级技巧 帮助读者提升编程水平 更加高效地使用这两种强大的编程语言 一 指针运算与内存管理 C C
  • C 语言文件读取全指南:打开、读取、逐行输出

    C 语言中的文件读取 要从文件读取 可以使用 r 模式 FILE fptr 以读取模式打开文件 fptr fopen filename txt r 这将使 filename txt 打开以进行读取 在 C 中读取文件需要一点工作 坚持住 我
  • C++实现函数重载的原理

    一 函数重载的概念 C 中允许存在同名函数 但要求函数参数的类型 个数不同 这些同名函数就称为函数的重载 void func int a int b cout lt lt func int a int b lt lt endl void f

随机推荐

  • Qt视频播放器[QMediaPlayer+QVideowidget]

    目录 参考 一 安装K Lite 解码器 二 Qt代码结构 VideoPlayer pro main cpp videoplayer h 播放器 videoplayer cpp 播放器 videoplayer ui 播放器 playersl
  • Python爬虫抓取经过JS加密的API数据的实现步骤

    随着互联网的快速发展 越来越多的网站和应用程序提供了API接口 方便开发者获取数据 然而 为了保护数据的安全性和防止漏洞 一些API接口采用了JS加密技术这种加密技术使得数据在传输过程中更加安全 但也给爬虫开发带来了一定的难度 在面对经过J
  • 常用集成运放电路合集(简洁易懂,附Multisim仿真文件)

    电赛初试培训整理的常用的集成运放电路集合 尽可能地追求全面 本文省略繁琐的推导过程 直接给出电路及其功能 以便读者使用时进行查阅 由于每个电路的介绍可能相对简略 实际使用或学习时可在站内查阅资料 网上资料丰富 在此不再赘述 本文目的是提供一
  • 树莓派体验3 - SSH登录树莓派

    如果没有HDMI转接线 显示器 USB转TTL串口线 那么可以通过网络SSH远程登录的方式访问树莓派 无显示器使用SSH访问 开启SSH服务 首先 通过镜像版本号确认一下SSH是否默认开启 树莓派官网的release note中说明 201
  • SQL的使用规范

    高程序运行效率 优化应用程序 在SP编写过程中应该注意以下几点 a SQL的使用规范 i 尽量避免大事务操作 慎用holdlock子句 提高系统并发能力 ii 尽量避免反复访问同一张或几张表 尤其是数据量较大的表 可以考虑先根据条件提取数据
  • 小程序主体为个人的教育类小程序备案——教育APP备案问题

    今天微信小程序后台发了通知 看了一下 我的小程序选择了 教育分类 思考了一下 虽然我选择了 教育 但是我的小程序是属于字典工具类的 与教育备案没什么关联 解决的办法 删除教育分类 老老实实备案 我选择了 因为我想了解下个人主体的小程序能不能
  • VS2019下的GAMES101作业环境配置

    序 很久很久以前 好像看过这个 GAMES101 现代计算机图形学入门 闫令琪 哔哩哔哩 bilibili 里面好像还有一个实验 当时只是看了看视频里的热闹 并没有写实验 现在想想 还是写一写的好 万一以后用上了呢 虽然是个24K纯小白 估
  • 解决Logback日志不会每天生成新文件的问题

    logback配置文件 问题现象 上图是最初的logback的配置 线上发现经常不会按日生成日志文件 而是一个日志越来越大 只有在项目重启之后才会生成当天的日志文件 原因分析 该配置使用了基于时间的滚动切割策略 TimeBasedRolli
  • 离散数学模拟微信红包算法升级版

    可以自定义红包总金额 总包数 每包最小金额
  • 关于springboot的序列化和反序列化问题

    在springboot中有时候需要将Datatime的格式进行格式化 有时候Long型的数据超过16位传值到前端js中会丢失精度 解决这个问题需要将Long型先转为String类型在传值到前端 所以可以编写实现类继承ObjectMapper
  • PicoNeo3开发VR——小白教程

    不断更新中 欢迎大佬们来指导 纠错 导入PicoVRSDK 1 新创一个Unity工程 Unity版本最好选择2019 4以上版本 以及需配置好安卓环境 然后导入官方picoVRSDK 2 渲染设置 Graphics APIs暂不支持Vul
  • DirectShow系列讲座之二——Filter原理

    在上一讲中 笔者介绍了DirectShow的总体系统框架 从这一讲开始 我们要从程序员的角度 进一步深入探讨一下DirectShow的应用以及Filter的开发 在这之前 笔者首先要特别提一下微软提供的一个Filter测试工具 GraphE
  • SpringBoot 高级进阶

    目录标题 SpringBoot 高级 1 RabbitMQ概述 1 RabbitMQ简介 消息服务中两个重要概念 消息队列主要有两种形式的目的地 异步处理 应用解耦 流量削峰 核心概念 2 RabbitMQ运行机制 3 RabbitMQ安装
  • 分布式部署 Zabbix 监控平台

    分布式部署 Zabbix 监控平台 一 基本介绍 二 部署 LNMP 架构 1 配置 MySQL 服务 2 配置 Nginx PHP 服务 1 安装 Nginx 2 安装 PHP 3 修改 PHP 配置文件 4 启动脚本 三 部署 Zabb
  • 跨站脚本攻击XSS(最全最细致的靶场实战)

    一 XSS跨站漏洞 1 XSS简介 网站中包含大量的动态内容以提高用户体验 比过去要复杂得多 所谓动态内容 就是根据用户环境和需要 Web应用程序能够输出相应的内容 动态站点会受到一种名为 跨站脚本攻击 Cross Site Scripti
  • 教你如何快速下载python

    1 打开python官网 链接 py官网 2 找到自己要安装的版本 点击下载 3 下载 exe文件 打开 4 弹出标题为Install Python X X X X bit 的窗口 将下面的Add Python 打勾 点Install No
  • (一)软件架构概述

    1 系统结构 B S架构 Browser Server 浏览器 服务器的交互形式 Browser支持哪些语言 HTML CSS JavaScript 写HTML CSS JavaScript代码的这波人职位叫做 WEB 前端开发工程师 Ja
  • Python学习笔记(四)

    文章目录 1 进程 1 1 系统原生 OS 模块 创建进程 1 2 multiprocessing 模块 1 2 1 Process 单进程 1 2 2 Pool 进程池 1 3 subprocess 模块 使用外部子进程 2 线程 2 1
  • 爬虫 跨域请求 获取json数据 解决参数加密

    分析网址 提示 抓取对方信息是通过对方允许的 请不要违法操作 抓取其他个人有关信息 网址先发送了一个OPTIONS请求 Request URL http xxxxxxxx com Request Method OPTIONS Status
  • C++知识积累:内存对齐理解

    为什么要进行内存对齐 这是因为CPU的读取总是对齐的 举个例子 假设CPU是32位的 那么CPU每次读取的4字节数据的首地址都是4的倍数 也就是说 内存中数据首地址为4的倍数时 CPU一次操作就可以完成数据读取 假设有一个int型四字节大小