【C++指南】C++中的内存对齐规则及原因详解

news2024/11/15 8:59:06

           💓 博客主页:倔强的石头的CSDN主页 

           📝Gitee主页:倔强的石头的gitee主页

            ⏩ 文章专栏:《C++指南》

                                  期待您的关注

1b7335aca73b41609b7f05d1d366f476.gif

 

目录

引言

一、为什么要进行内存对齐

二、C++中的内存对齐规则

三、内存对齐示例讲解 

示例代码 

 运行结果解释

内存布局详细说明

结语


引言

在计算机科学中,内存对齐是一种数据存储方式,它要求某些类型的数据必须存储在特定地址上。这种要求是由硬件架构决定的,不同的处理器可能有不同的对齐要求。C++作为一种底层抽象程度较高的编程语言,允许开发者通过编译器选项或特定语法来控制数据的内存布局,以满足这些硬件需求。

本文将详细介绍C++中的内存对齐规则及其背后的原理。

一、为什么要进行内存对齐

内存对齐的原因主要可以归结为两个方面:性能提升平台兼容性

(下方加红的两点是最主要的两个原因)

  1. 性能提升
    • 减少CPU访问次数现代CPU通常一次可以读取多个字节(如4个或8个字节)。如果一个数据项没有正确对齐,那么CPU可能需要两次或更多次的内存访问才能完成对该数据项的加载或存储操作,这会显著降低程序运行速度。例如,在32位系统上,如果一个4字节的整数没有4字节对齐,那么访问这个整数时可能会跨越两个不同的内存块,导致性能下降
    • 优化内存带宽利用:内存带宽是有限的,对齐数据可以减少因读取未对齐数据而产生的额外开销,使内存带宽得到更有效的利用。
  2. 平台兼容性
    • 硬件限制不是所有的硬件平台都能无差别地访问任意地址上的任意数据。某些硬件平台(如某些架构的CPU)要求特定类型的数据必须从特定的内存地址开始存取,否则可能引发硬件异常或错误。内存对齐可以确保数据在存储时满足这些硬件要求,从而提高程序的兼容性和稳定性。
    • 移植性:编写可移植的代码是软件开发中的一个重要目标。内存对齐有助于减少因不同平台间硬件差异而导致的兼容性问题,使得同一份代码能够在不同的硬件平台上正常运行。

二、C++中的内存对齐规则

C++标准规定了每个数据类型的最小对齐要求,这些要求通常是该类型大小的倍数。例如,int类型(假设为4字节)应该至少4字节对齐,而double类型(假设为8字节)则应8字节对齐。

具体规则如下:

  • 第⼀个成员在与结构体偏移量为0的地址处。
  • 其他成员变量要对齐到某个数字(对⻬数)的整数倍的地址处。
  • 基本数据类型:对于内置类型如charshortintlongfloatdouble等,它们的对齐方式通常是其自身大小。
  • 结构体和类:对于复合类型,如结构体或类,其成员变量的对齐方式取决于各自的基本类型。结构体或类的整体对齐要求是其所有成员中最大的对齐要求。
  • 数组:数组的对齐方式与其元素类型相同。
  • 注意:对⻬数 = 编译器默认的⼀个对⻬数 与 该成员大小的较小值
  • 比如Visual Studio默认的对⻬数为8

三、内存对齐示例讲解 

示例代码 

#include <iostream>
#include <type_traits>

// 定义一个结构体
struct MyStruct {
    char a;     // 1 byte
    int b;      // 4 bytes
    double c;   // 8 bytes
    short d;    // 2 bytes
};

int main() {
    // 打印每个成员的偏移量
    std::cout << "Offset of a: " << offsetof(MyStruct, a) << std::endl;
    std::cout << "Offset of b: " << offsetof(MyStruct, b) << std::endl;
    std::cout << "Offset of c: " << offsetof(MyStruct, c) << std::endl;
    std::cout << "Offset of d: " << offsetof(MyStruct, d) << std::endl;

    // 打印每个成员的对齐要求
    std::cout << "Alignment of char: " << alignof(char) << std::endl;
    std::cout << "Alignment of int: " << alignof(int) << std::endl;
    std::cout << "Alignment of double: " << alignof(double) << std::endl;
    std::cout << "Alignment of short: " << alignof(short) << std::endl;

    // 打印结构体的大小和对齐要求
    std::cout << "Size of MyStruct: " << sizeof(MyStruct) << std::endl;
    std::cout << "Alignment of MyStruct: " << alignof(MyStruct) << std::endl;

    // 解释内存布局
    std::cout << "\nMemory Layout Explanation:\n";
    std::cout << "a (1 byte) at offset 0\n";
    std::cout << "Padding (3 bytes) to align b to 4-byte boundary\n";
    std::cout << "b (4 bytes) at offset 4\n";
    std::cout << "Padding (4 bytes) to align c to 8-byte boundary\n";
    std::cout << "c (8 bytes) at offset 8\n";
    std::cout << "d (2 bytes) at offset 16\n";
    std::cout << "Padding (6 bytes) to make the total size a multiple of the largest alignment (8 bytes)\n";

    return 0;
}

 运行结果解释

 

内存布局详细说明

  1. a (1 byte):位于偏移量0处。
  2. Padding (3 bytes):为了使b对齐到4字节边界,插入3字节的填充。
  3. b (4 bytes):位于偏移量4处。
  4. Padding (4 bytes):为了使c对齐到8字节边界,插入4字节的填充。
  5. c (8 bytes):位于偏移量8处。
  6. d (2 bytes):位于偏移量16处。
  7. Padding (6 bytes):为了使整个结构体的大小是8字节的倍数,插入6字节的填充。

 

结语

C++中的内存对齐是一个复杂但至关重要的概念。

要求开发者在编写代码时考虑数据在内存中的存储方式,以确保程序的性能和兼容性。通过遵循内存对齐的规则,开发者可以编写出更高效、更稳定的C++程序。同时,了解内存对齐的原因也有助于开发者更好地理解计算机硬件的工作原理和C++语言的底层机制。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2165767.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring Boot 进阶-第一个程序HelloWorld

从我们学习编程语言开始,每次入门一个语言都是从Hello World开始,当然这里我们也不例外。首先从一个简单的HelloWorld程序开始。 既然是要学着做Java Web开发,那么首先需要了解的就是如何去编写一个RESTFul风格的接口,这里我们就需要引入一个pom的依赖。 <dependency&g…

矩阵分析 学习笔记4 内积与Gram矩阵

内积 定义 由于对称&#xff0c;第二变元线性那第一变元也线性了。例如这个&#xff1a;

【YashanDB知识库】yashandb执行包含带oracle dblink表的sql时性能差

本文内容来自YashanDB官网&#xff0c;具体内容请见https://www.yashandb.com/newsinfo/7396959.html?templateId1718516 问题现象 yashandb执行带oracle dblink表的sql性能差&#xff1a; 同样的语句&#xff0c;同样的数据&#xff0c;oracle通过dblink访问远端oracle执行…

spring学习 【基础】

目录 1.将bean交给spring容器管理 1. 编写bean对象 2. 在resources目录下创建spring config xml文件&#xff0c;并管理bean对象 3. spring容器管理工厂 2.Spring Bean 生命周期 2.1 Spring Bean初始化方法 2.1.1 自定义初始化方法 2.1.2 实现接口(InitializingBean)…

Spring6梳理12——依赖注入之注入Map集合类型属性

以上笔记来源&#xff1a; 尚硅谷Spring零基础入门到进阶&#xff0c;一套搞定spring6全套视频教程&#xff08;源码级讲解&#xff09;https://www.bilibili.com/video/BV1kR4y1b7Qc 12 依赖注入之注入Map集合类型属性 12.1 创建Student类和Teacher类 Student类中创建了run…

灵当CRM multipleUpload.php 文件上传致RCE漏洞复现

0x01 产品描述&#xff1a; 灵当CRM是一款专为中小企业量身定制的智能客户关系管理工具&#xff0c;由上海灵当信息科技有限公司开发和运营。该系统广泛应用于多个行业&#xff0c;包括金融、教育、医疗、IT服务及房地产等领域&#xff0c;旨在满足企业对客户个性化管理的需求&…

集合ArrayList常用方法

源代码&#xff1a; 输出结果&#xff1a;

小米Civi2机型工程固件 资源预览 刷写说明 与nv损坏去除电阻图示

小米Civi2机型机型代码为:ziyi。次期开始讲在博文中陆续解析机型nv损坏修复的一些步骤与当前机型去除校验电阻相关的图示与说明。注意。米系列机型有串码校验。去除电阻需要一定的技术,请谨慎操作。 通过博文了解 1💝💝💝-----此机型工程固件的资源刷写注意事项 2�…

【计算机网络 - 基础问题】每日 3 题(二十四)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/fYaBd &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 C 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏&…

音乐服务器测试报告

项目背景 该音乐服务器系统使用的是前后端分离的方式来实现,将相关数据存储到数据库中, 且将其部署到云服务器上. 前端主要构成部分有: 登录页面, 列表页面, 喜欢页面, 添加歌曲4个页面组成. 通过结合后端实现了主要的功能: 登录, 播放音乐, 添加音乐, 收藏音乐, 删除音乐, 删…

uniapp实现在表单中展示多个选项,并且用户可以选择其中的一个或多个选项

前言 uni-data-checkbox是uni-app的一个组件,用于在表单中展示多个选项,并且用户可以选择其中的一个或多个选项。该组件可以通过设置不同的参数来控制选项的样式、布局和行为。 提示:以下是本篇文章正文内容,下面案例可供参考 uni-data-checkbox组件具有以下特点:: 1、跨…

Git 工作区、暂存区与修改全解析

工作区和暂存区是 Git 中一个非常重要的概念&#xff0c;弄明白了他们&#xff0c;就弄明白了 Git 的很多操作到底干了什么。 ‍ 工作区&#xff08;Working Directory&#xff09; 工作区&#xff0c;就是一个目录&#xff0c;比如我的 LearnGit ​文件夹就是一个工作区&am…

JavaScript --模版字符串用反引号

用反引号 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-width, i…

SpringBoot集成阿里easyexcel(一)基础导入导出

easyexcel主要用于excel文件的读写&#xff0c;可使用model实体类来定义文件读写的模板&#xff0c;对开发人员来说实现简单Excel文件的读写很便捷。可参考官方文档 https://github.com/alibaba/easyexcel 一、引入依赖 <!-- 阿里开源EXCEL --><dependency><gr…

《深度学习》ResNet残差网络、BN批处理层 结构、原理详解

目录 一、关于ResNet 1、什么是ResNet 2、传统卷积神经网络存在的问题 1&#xff09;梯度消失和梯度爆炸问题 2&#xff09;训练困难 3&#xff09;特征表示能力受限 4&#xff09;模型复杂度和计算负担 3、如何解决 1&#xff09;解决梯度问题 BN层重要步骤&#xff1a; 2…

Gstreamer中,使用mp4或者flv作为视频源去推流RTP等视频流时,需要先解码在编码才能正常

前言&#xff1a; 在Gstreamer中&#xff0c;视频源可以有很多&#xff0c;在很多时候&#xff0c;我们为了测试&#xff0c;会使用MP4等文件作为视频源进行测试&#xff0c;但是发现无论是我自己测试&#xff0c;还是很多网上的命令&#xff0c;都需要先对mp4的h264数据解码以…

等保测评实战:构建企业网络安全的铜墙铁壁

在数字化转型的浪潮下&#xff0c;企业面临的网络安全威胁日益复杂多变。信息安全等级保护&#xff08;等保&#xff09;测评作为国家强制性标准&#xff0c;不仅检验着企业的网络安全防护能力&#xff0c;更是企业构建网络安全“铜墙铁壁”的实战指南。本文将从实战角度&#…

华为云徐峰:AI赋能应用现代化,加速软件生产力跃升

2024年9月19日&#xff0c;在华为全联接大会2024的“AI赋能应用现代化&#xff0c;加速软件生产力跃升”论坛上&#xff0c;华为云PaaS服务产品部部长徐峰发表了主题演讲&#xff0c;介绍了未来应用智能化演进趋势&#xff0c;分享了智能化应用的行业实践&#xff0c;并发布了华…

Elasticsearch 启动后在浏览器输入http://localhost:9200 访问失败

windows Elasticsearch 启动后在浏览器输入http://localhost:9200 访问失败 文章目录 前言本地下载安装了个elasticsearch&#xff0c;启动成功了&#xff0c;在本地访问http://localhost:9200 无法访问&#xff01;&#xff01;&#xff01;难受了一下。 一、windows Elastics…

从文本图片到多模态:3D 数字人打开企业全域商业增长新空间

摘要&#xff1a;数字化与AI浪潮推动各行业变革&#xff0c;内容形式也发生巨变&#xff0c;从文本到多媒体的多模态表达&#xff0c;标志着内容创造走向升维。AIGC 3D生成技术的突飞猛进&#xff0c;彻底打破了传统3D内容生产门槛高、周期长、成本高昂的问题。将3D数字人的打造…