C++内存对齐

在 C++ 中,内存对齐 是一种编译器和硬件协作的机制,用于将数据存储在内存中时按照一定的规则进行排列,以提高数据访问的效率。其目的是确保数据在内存中的地址满足硬件对齐要求,并优化 CPU 访问速度。

C++ 中内存对齐的基本概念

  1. 对齐单位(Alignment Unit): 每种数据类型有其对应的对齐单位,通常是数据类型的大小。例如:
    1. char 类型的大小为 1 字节,对齐单位为 1。
    2. int 类型的大小为 4 字节,对齐单位为 4。
    3. double 类型的大小为 8 字节,对齐单位为 8。
  2. 对齐规则:
    1. 单个变量:变量的地址必须是其对齐单位的整数倍。
    2. 结构体中的变量:每个成员变量按照其对齐单位对齐。
      1. 整个结构体的大小是最大对齐单位的整数倍(即结构体的大小会被填充到满足最大成员对齐单位的倍数)。

C++ 中内存对齐的示例

示例 1:普通结构体对齐
#include <iostream>
using namespace std;

struct Example {
    char a;   // 占 1 字节
    int b;    // 占 4 字节
    short c;  // 占 2 字节
};

int main() {
    cout << "Size of Example: " << sizeof(Example) << endl;
    return 0;
}

分析:

  1. char a 的起始地址是 0,大小为 1 字节。
  2. int b 必须从 4 的倍数地址开始,因此在 a 后插入 3 个填充字节。
  3. short c 的对齐单位是 2,其地址为 8
  4. 结构体大小必须是最大对齐单位(4)的倍数,因此在 c 后填充 2 个字节。

最终,Example 的大小为 12 字节

示例 2:使用 #pragma pack 修改对齐方式

可以使用 #pragma pack 指令改变对齐方式:

#include <iostream>
using namespace std;

#pragma pack(1) // 设置对齐单位为 1 字节
struct PackedExample {
    char a;
    int b;
    short c;
};
#pragma pack() // 恢复默认对齐

int main() {
    cout << "Size of PackedExample: " << sizeof(PackedExample) << endl;
    return 0;
}

分析:

  1. char a 占 1 字节,无填充。
  2. int b 紧接在 a 后,占 4 字节。
  3. short c 紧接在 b 后,占 2 字节。
  4. 总大小为 7 字节,没有填充。

C++ 中的内存对齐控制

  1. #pragma pack:
    1. 用于设置对齐单位。
    2. 例如:#pragma pack(2) 将所有变量的对齐单位限制为 2 字节。
  2. alignasalignof: C++11 提供了关键字 alignasalignof,用于设置和查询对齐方式。
#include <iostream>
alignas(16) struct AlignedStruct {
    int a;
    double b;
};

int main() {
    std::cout << "Alignment of AlignedStruct: " << alignof(AlignedStruct) << std::endl;
    std::cout << "Size of AlignedStruct: " << sizeof(AlignedStruct) << std::endl;
    return 0;
}


  • alignas(16) 将结构体对齐到 16 字节。
  • alignof(AlignedStruct) 查询结构体的对齐单位。

默认对齐: 编译器会根据目标平台和数据类型的特性选择默认对齐方式。

C++ 中内存对齐的优缺点

优点:

  1. 提高程序运行效率,特别是在多核 CPU 或 SIMD(单指令多数据)操作中。
  2. 遵循硬件架构对对齐的要求,避免未对齐访问导致的性能问题。
缺点:
  1. 增加内存占用,因为填充字节(Padding)会占用额外空间。
  2. 对于小型嵌入式系统,可能需要手动调整对齐方式以节省内存。

求结构体所占空间的大小

  1. 结构体成员当中所占空间最大的类型 按照它来对齐 结果一定是它的整数倍
  2. 要按照定义的流程进行空间的分配
  3. 整数倍地址对齐
  4. 当结构体成员为数组时 需要把数组拆分成很多个变量处理

#include<iostream>

using namespace std;

struct {

char b;

int a;        

char c;

} s;

int main() {

cout << sizeof(s);

return 0;

}

4.位域

1.如果相邻的成员时同种类型可以尝试往一个单位进行放置 如果放不下就两个单位处理

2.成员不允许跨单位放置

#include<iostream>

using namespace std;

struct {//位域

char b:1;

char a:7;        

char c:1;

}s;

int main() {

cout << sizeof(s);

return 0;

}

为什么需要内存对齐

1. 硬件访问效率

大多数 CPU 是按照固定宽度的内存总线来访问内存的(比如 4 字节或 8 字节),而非逐字节操作。如果数据未对齐,CPU 可能需要执行多次内存访问才能完成一次数据读取或写入,导致性能下降。

示例:

假设一个 4 字节的 int 数据存储在一个非对齐地址(比如地址 0x01),CPU 需要:

  1. 读取 0x00-0x03 的数据(第一段)。
  2. 再读取 0x04-0x07 的数据(第二段)。
  3. 从两段数据中提取有效字节。

而如果 int 对齐到 4 字节边界(地址为 0x04),只需要一次读取即可完成。

2. 遵循硬件架构要求

某些硬件架构(如一些 RISC 处理器)严格要求数据必须对齐。如果不对齐的情况下访问内存,会触发硬件异常或错误。

例如:

  • 在 ARM 和 SPARC 架构中,未对齐访问可能直接导致程序崩溃。
  • 在 x86 架构中,虽然支持未对齐访问,但会降低性能。

3. 优化内存缓存(Cache)性能

CPU 的缓存以缓存行(Cache Line)的形式存储数据(通常是 32 字节或 64 字节)。对齐数据可以减少跨缓存行的访问,从而提高缓存命中率,降低内存访问延迟。

举例:

假设缓存行大小为 64 字节:

  • 对齐数据可以完全装入一个缓存行中。
  • 未对齐数据可能跨越两个缓存行,导致需要多次读取缓存甚至内存,降低性能。

4. 简化硬件设计

对齐的数据访问模式可以让硬件设计更简单高效。例如:

  • 内存地址和对齐单位是 2 的幂关系,硬件通过位运算即可快速判断是否对齐。
  • 对齐后,内存访问的边界计算更加规整,减少硬件复杂度。

5. 提升编译器优化能力

编译器在生成机器码时,如果数据是对齐的,可以生成更高效的指令序列;而未对齐的数据访问可能需要额外的指令来处理,例如:

  • 数据分割和拼接。
  • 调整偏移地址。

6. 程序稳定性和跨平台兼容性

不同平台可能对数据对齐的要求不同。对齐数据可以避免在跨平台运行时出现兼容性问题(如硬件错误或性能差异)。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

365天深度学习训练营-第P6周:VGG-16算法-Pytorch实现人脸识别

&#x1f368; 本文为&#x1f517;365天深度学习训练营中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 文为「365天深度学习训练营」内部文章 参考本文所写记录性文章&#xff0c;请在文章开头带上「&#x1f449;声明」 &#x1f37a;要求&#xff1a; 保存训练过…

SAP SD学习笔记15 - 返品处理流程2 - 参照请求传票(发票)来生成返品传票

上一章讲了返品处理&#xff08;退货处理&#xff09;的流程。 SAP SD学习笔记14 - 返品处理&#xff08;退货处理&#xff09;的流程以及系统实操&#xff0c;比如 返品传票&#xff1b;请求Block标记&#xff1b;收到退货之后的处理&#xff0c;请求传票的登录_sap 销售返品…

Flutter 1.1:下载Flutter环境

1、在AS中下载Flutter插件 在setting的Plugins中下载Flutter&#xff0c;如图所示&#xff0c;可以直接进行搜索查找 2、下载flutter的sdk源代码 flutter中文文档学习 通过Git下载SDK源代码 git clone -b stable https://github.com/flutter/flutter.git3、配置系统变量 3…

电子应用设计方案-31:智能AI音响系统方案设计

智能 AI 音响系统方案设计 一、引言 智能 AI 音响作为一种新兴的智能家居设备&#xff0c;通过融合语音识别、自然语言处理、音频播放等技术&#xff0c;为用户提供便捷的语音交互服务和高品质的音乐体验。本方案旨在设计一款功能强大、性能稳定、用户体验良好的智能 AI 音响系…

损失函数分类

1. NLLLoss&#xff08;负对数似然损失&#xff09; 定义&#xff1a; 直接对预测的概率 p(yi) 的负对数求平均。通常配合 Softmax 使用&#xff0c;输入为对数概率。 优点&#xff1a; 对离散分类问题效果良好。更灵活&#xff0c;用户可以自行计算 Softmax。 缺点&#x…

聊聊Flink:这次把Flink的触发器(Trigger)、移除器(Evictor)讲透

一、触发器(Trigger) Trigger 决定了一个窗口&#xff08;由 window assigner 定义&#xff09;何时可以被 window function 处理。 每个 WindowAssigner 都有一个默认的 Trigger。 如果默认 trigger 无法满足你的需要&#xff0c;你可以在 trigger(…) 调用中指定自定义的 tr…

oracle中删除指定前缀的表

近期接手做的项目&#xff0c;发觉数据库中有许多多余的表。究其原因&#xff0c;应该是同事贪图方便&#xff0c;将过去做过的项目复制粘贴&#xff0c;然后修修改改。包括数据库也是克隆过来的&#xff0c;然后又没有删除本项目多余的表&#xff0c;结果经过几个轮回&#xf…

Mybatis:CRUD数据操作之修改数据update

Mybatis基础环境准备请看&#xff1a;Mybatis基础环境准备 本篇讲解Mybati数据CRUD数据操作之修改数据 用户在该页面书写需要修改的数据&#xff0c;点击 提交 按钮&#xff0c;就会将数据库中对应的数据进行修改。注意一点&#xff0c;如果哪儿个输入框没有输入内容&#xff…

遥感数据集:FTW全球农田边界和对应影像数据,约160万田块边界及7万多个样本

Fields of The World (FTW) 是一个面向农业田地边界实例分割的基准数据集&#xff0c;旨在推动机器学习模型的发展&#xff0c;满足全球农业监测对高精度、可扩展的田地边界数据的需求。该数据集由kerner-lab提供&#xff0c;于2024年8月28日发布&#xff0c;主要特征包括&…

从0开始linux(38)——线程(1)线程概念

欢迎来到博主专栏&#xff1a;从0开始linux 博主ID&#xff1a;代码小豪 文章目录 进程与线程线程概念线程的优点线程的独立数据 进程与线程 如果要理解线程&#xff0c;那么进程将会时绕不开的点。首先我们回顾一下我们之前在进程章节当中是如何描述进程的&#xff1f; 进程&…

使用 PDF API 合并 PDF 文件

内容来源&#xff1a; 如何在 Mac 上合并 PDF 文件 1. 注册与认证 您可以注册一个免费的 ComPDFKit API 帐户&#xff0c;该帐户允许您在 30 天内免费无限制地处理 1,000 多个文档。 ComPDFKit API 使用 JSON Web Tokens 方法进行安全身份验证。从控制面板获取您的公钥和密钥&…

【聊天室后端服务器开发】语音转换子服务

概述 实现逻辑 服务器搭建流程分析 基于gflags模块进行参数解析 RPC信息&#xff1a;当前服务器的地址端口&#xff0c;主要用于搭建RPC服务器的监听地址信息服务注册信息 注册中心的地址端口&#xff1a;向服务器中心进行服务注册外部访问地址端口&#xff1a;告知注册中心的…

w064基于springboot的高校学科竞赛平台

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以查看文章末尾⬇️联系方式获取&#xff0c;记得注明来意哦~&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0…

UCOS-II 自学笔记

摘抄于大学期间记录在QQ空间的一篇自学笔记&#xff0c;当前清理空间&#xff0c;本来想直接删除掉的&#xff0c;但是感觉有些舍不得&#xff0c;因此先搬移过来。 一、UC/OS_II体系结构 二、UC/OS_II中的任务 1、任务的基本概念 在UCOS-II中&#xff0c;通常把一个大型任…

《Python基础》之Python中可以转换成json数据类型的数据

目录 一、JSON简介 JSON有两种基本结构 1、对象&#xff08;Object&#xff09; 2、数组&#xff08;Array&#xff09; 二、将数据装换成json数据类型方法 三、在Python中&#xff0c;以下数据类型可以直接转换为JSON数据类型 1、字典&#xff08;Dictionary&#xff09…

Android -- 简易音乐播放器

Android – 简易音乐播放器 播放器功能&#xff1a;* 1. 播放模式&#xff1a;单曲、列表循环、列表随机&#xff1b;* 2. 后台播放&#xff08;单例模式&#xff09;&#xff1b;* 3. 多位置同步状态回调&#xff1b;处理模块&#xff1a;* 1. 提取文件信息&#xff1a;音频文…

纯Go语言开发人脸检测、瞳孔/眼睛定位与面部特征检测插件-助力GoFly快速开发框架

前言​ 开发纯go插件的原因是因为目前 Go 生态系统中几乎所有现有的人脸检测解决方案都是纯粹绑定到一些 C/C 库&#xff0c;如 ​​OpenCV​​ 或 ​​​dlib​​​&#xff0c;但通过 ​​​cgo​​​ 调用 C 程序会引入巨大的延迟&#xff0c;并在性能方面产生显著的权衡。…

uniapp中父组件数组更新后与页面渲染数组不一致实战记录

简单描述一下业务场景方便理解: 商品设置功能,支持添加多组商品(点击添加按钮进行增加).可以对任意商品进行删除(点击减少按钮对选中的商品设置进行删除). 问题: 正常添加操作后,对已添加的任意商品删除后,控制台打印数组正常.但是与页面显示不一致.已上图为例,选中尾…

【Figma】中文版安装

一、软件安装包下载 打开官网链接https://www.figma.com/downloads/下载相应安装包 或使用我已下载好的链接&#xff1a; FigmaSetup.exe 链接: https://pan.baidu.com/s/113eQ8JRETdeOwUp2B3uieA?pwd4vep 二、安装流程 1.点击安装包 2.选择在浏览器登录 3.输入账号密码&a…

SpringBoot框架在宠物领养系统中的应用

摘 要 如今社会上各行各业&#xff0c;都在用属于自己专用的软件来进行工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。互联网的发展&#xff0c;离不开一些新的技术&#xff0c;而新技术的产生往往是为了解决现有问题而产生的。针对于宠物领养…