当前位置: 首页 > news >正文

内存对齐的原理和使用

1. 什么是内存对齐?

内存对齐是指将数据存储在内存中时,按照数据类型的大小,将数据放在特定的内存边界上。例如,4 字节的 int 通常放在能够被 4 整除的地址上,8 字节的 double 则放在能被 8 整除的地址上。

2. 为什么需要内存对齐?

内存对齐有几个关键的原因:

2.1 提高 CPU 访问速度
  • CPU 访问内存时,会一次性读取一定数量的字节(通常是 4、8 或 16 字节)。当数据地址是对齐的,CPU 可以在一次内存读取操作中完整读取数据,这显著提升了效率。
  • 如果数据没有对齐,CPU 可能需要执行多次内存读取操作来获取完整的数据。例如,如果一个 4 字节的 int 存储在一个未对齐的位置(比如 3 字节边界上),那么 CPU 需要读取两次内存块,将其拼接成一个完整的数据。这会降低系统性能。
2.2 硬件要求
  • 一些处理器架构(如早期的 RISC 处理器或某些嵌入式系统)不允许从非对齐的内存地址读取数据。如果数据没有对齐,硬件可能会抛出错误,导致程序崩溃。
  • 对于允许非对齐访问的架构(如大多数 x86 处理器),虽然可以处理非对齐数据,但这往往伴随着性能上的显著开销。
2.3 避免额外的计算复杂性
  • 如果数据不对齐,编译器和硬件需要额外计算如何正确读取和写入数据。这增加了编译器和 CPU 的复杂性,也可能会导致更高的功耗。

3. 内存对齐的原理

内存对齐遵循以下基本规则:

  • 数据的起始地址必须是它大小的整数倍。例如,4 字节的 int 变量的地址通常是 4 的倍数,8 字节的 double 变量的地址是 8 的倍数。
  • 现代编译器通常会为不同类型的数据设置默认的对齐规则,确保数据存储在合适的内存地址上。

4. 内存对齐的代价:填充字节

为了满足对齐要求,编译器可能会在内存中引入一些填充字节(padding bytes),这些字节不会存储有效数据,但它们确保后续的数据地址是对齐的。

示例:

假设有一个包含不同类型成员的结构体:

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

在 32 位系统上,内存对齐可能是这样的:

| a (1 byte) | padding (3 bytes) | b (4 bytes) | c (2 bytes) | padding (2 bytes) |
  • a 占 1 字节,但 b 是 4 字节的 int,需要对齐到 4 字节边界,因此 a 后面有 3 个填充字节。
  • c 是 2 字节的 short,为了对齐结构体的总大小,也可能引入额外的 2 字节填充。

总大小为 12 字节,而不是简单的 7 字节。

5. 内存对齐的影响

  • 性能提升:对齐使得 CPU 能够更高效地访问内存,尤其是当大量数据处理时,这一点显得尤为重要。
  • 空间开销:虽然内存对齐可能引入填充字节,增加内存使用,但这通常是必要的权衡,因为提升了数据访问效率。

6. 手动控制对齐

在 C++ 中,可以使用 #pragma packalignas 关键字来手动调整结构体的对齐方式。例如,#pragma pack(1) 可以让编译器不插入填充字节,减少内存占用。但这可能会牺牲性能,甚至导致某些平台上的错误。

7.使用#pragma pack 来关闭内存对齐

手动控制内存对齐手动控制内存对齐是一种手段,可以通过编译器指令调整数据结构的内存对齐方式,以减少内存浪费或满足特殊的内存布局需求。通常情况下,编译器会自动为数据类型安排合理的对齐,但在某些场景下,你可能需要手动修改对齐策略。常用的手段包括 #pragma packalignas 关键字。下面详细解释这两种方法:

1. #pragma pack

#pragma pack 是一种预处理指令,用来控制结构体或类的对齐方式。它可以通过设定字节边界来调整结构体中的填充字节。

语法:
#pragma pack(n)
  • 其中 n 表示对齐字节边界,例如 1248 等。编译器会强制将结构体成员对齐到 n 字节的边界上。
示例:
#pragma pack(1)
struct Example {char a;  // 1字节int b;   // 4字节short c; // 2字节
};
#pragma pack() // 恢复默认对齐

#pragma pack(1) 下,编译器将强制所有成员不插入任何填充字节,对齐到 1 字节边界,结构体内存布局如下:

| a (1 byte) | b (4 bytes) | c (2 bytes) |

此时,整个结构体大小为 7 字节,没有任何填充字节。

不使用 #pragma pack 的默认布局:

如果不使用 #pragma pack(1),编译器会按照默认对齐方式处理。以 4 字节对齐为例,Example 结构体的默认内存布局为:

| a (1 byte) | padding (3 bytes) | b (4 bytes) | c (2 bytes) | padding (2 bytes) |

默认情况下,int b 需要对齐到 4 字节边界,因此在 a 后面插入了 3 个字节的填充,使得 b 正好对齐到 4 字节边界,最后结构体大小为 12 字节

优缺点:
  • 优点:可以减少不必要的内存填充,尤其在数据存储、网络传输等场景下,可以节省内存。
  • 缺点:强制对齐到小字节边界可能导致性能下降,尤其是在现代 CPU 上,非对齐的内存访问可能会引起多次内存访问,导致系统性能变差。

8 使用alignas 关键字

alignas 是 C++11 引入的关键字,它可以在声明变量或结构体成员时,指定某个成员的对齐方式。

语法:
alignas(n) type var;
  • 其中 n 是对齐要求的字节数,type 是变量类型,var 是变量名称。alignas 可以为数据结构的某个特定成员或整个结构体设置对齐。
示例:
struct Example {char a;                  // 1字节alignas(8) int b;        // 强制 b 对齐到 8 字节short c;                 // 2字节
};

在这个例子中,int b 强制对齐到 8 字节边界。内存布局将变为:

| a (1 byte) | padding (7 bytes) | b (4 bytes) | c (2 bytes) | padding (2 bytes) |

整个结构体大小为 16 字节。相比默认情况下的对齐方式(4 字节对齐),b 现在被强制对齐到 8 字节,因此插入了更多的填充字节以确保对齐。

对齐整个结构体:

alignas 还可以用于整个结构体的对齐,例如:

struct alignas(16) Example {char a;int b;
};

这会确保 Example 结构体的起始地址是 16 字节对齐的,通常在需要满足特定硬件需求或 SIMD(单指令多数据)操作时会使用。

优缺点:
  • 优点alignas 提供了更细粒度的控制,允许为特定变量或结构体自定义对齐方式。
  • 缺点:过度使用可能增加填充字节,从而浪费内存;同时,也会影响性能,尤其是在对齐过度的情况下。

3. #pragma packalignas 的比较

  • 适用范围#pragma pack 主要用于控制整个结构体的对齐方式,而 alignas 可以细粒度控制特定成员或整个结构体的对齐。
  • 灵活性alignas 更灵活,因为它可以精确控制特定成员的对齐,而 #pragma pack 是全局性的。
  • 兼容性#pragma pack 是一种编译器指令,不同编译器可能有不同的实现和支持;alignas 是标准的 C++ 关键字,跨平台兼容性更好。

相关文章:

内存对齐的原理和使用

1. 什么是内存对齐? 内存对齐是指将数据存储在内存中时,按照数据类型的大小,将数据放在特定的内存边界上。例如,4 字节的 int 通常放在能够被 4 整除的地址上,8 字节的 double 则放在能被 8 整除的地址上。 2. 为什么…...

搭建企业级私有仓库harbor

华子目录 harbor简介实验环境准备下载软件包安装docker-cehosts解析 实验步骤配置https加密传输解压进入解压目录,修改文件配置启动harbor 测试客户端配置harbor本地加速器注意 通过docker compose管理harbor harbor简介 harbor是由wmware公司开源的企业级docker r…...

互联网前后端分离的开发场景,一般会员和数据权限的判断是放在前端还是后端?

推荐学习文档 golang应用级os框架,欢迎stargolang应用级os框架使用案例,欢迎star案例:基于golang开发的一款超有个性的旅游计划app经历golang实战大纲golang优秀开发常用开源库汇总想学习更多golang知识,这里有免费的golang学习笔…...

李宏毅机器学习2022-HW8-Anomaly Detection

文章目录 TaskBaselineReportQuestion2 Code Link Task 异常检测Anomaly Detection 将data经过Encoder,在经过Decoder,根据输入和输出的差距来判断异常图像。training data是100000张人脸照片,testing data有大约10000张跟training data相同…...

用户体验分享 | YashanDB V23.2.3安装部署

近期崖山新版体验过程中,总能看到用户提问:openssl版本问题、monit命令找不到问题、yashan用户权限问题、数据库重装问题 今日整理了多位用户的安装经验,希望能够帮助到大家~ 1.Lucifer三思而后行 :YashanDB 个人版数据库安装部…...

【漏洞复现】泛微OA E-Office /E-mobile/App/init.php 任意文件上传漏洞

免责声明: 本文旨在提供有关特定漏洞的信息,以帮助用户了解潜在风险。发布此信息旨在促进网络安全意识和技术进步,并非出于恶意。读者应理解,利用本文提到的漏洞或进行相关测试可能违反法律或服务协议。未经授权访问系统、网络或应用程序可能导致法律责任或严重后果…...

SpringCloudEureka实战:搭建EurekaServer

1、依赖引入 <dependencies><!-- 注册中心 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId></dependency> </dependencies> <de…...

DataLight(V1.4.5) 版本更新,新增 Ranger、Solr

DataLight&#xff08;V1.4.5&#xff09; 版本更新&#xff0c;新增 Ranger、Solr DataLight 迎来了重大的版本更新&#xff0c;现已发布 V1.4.5 版本。本次更新对平台进行了较多的功能拓展和优化&#xff0c;新增了对 Ranger 和 Solr 服务组件的支持&#xff0c;同时对多项已…...

深度解析:Python蓝桥杯青少组精英赛道与高端题型概览

目录 一、蓝桥杯青少组简介二、赛项组别与年龄范围三、比赛内容与题型1. 基础知识范围2. 题型设置2.1 选择题2.2 编程题 3. 考试时长 四、奖项设置与激励措施五、总结 一、蓝桥杯青少组简介 蓝桥杯全国软件和信息技术专业人才大赛&#xff08;简称“蓝桥杯”&#xff09;是由工…...

如何使用SCCMSecrets识别SCCM策略中潜在的安全问题

关于SCCMSecrets SCCMSecrets是一款针对SCCM策略的安全扫描与检测工具&#xff0c;该工具旨在提供一种有关 SCCM 策略的全面安全检测方法。 该工具可以从各种权限级别执行&#xff0c;并将尝试发现与策略分发相关的潜在错误配置。除了分发点上托管的包脚本外&#xff0c;它还将…...

Qt 信号重载问题--使用lambda表达式--解决方法

在connect()中&#xff0c;使用lambda表达式时遇到信号重载&#xff0c;无法识别使用哪个参数时&#xff0c;可通过以下方法处理&#xff1a; 1. 使用QOverload: Qt5.7才有 connect(comboBox,QOverload<int>::of(&QComboBox::currentIndexChanged), [](int index)…...

并行编程实战——TBB框架的应用之一Supra的基础

一、TBB的应用 在前面分析了TBB框架的各种基本知识和相关的基础应用。这些基础的应用很容易通过学习文档或相关的代码来较为轻松的掌握。为了能够更好的理解TBB框架的优势&#xff0c;这里从一个开源的应用程序来分析一下TBB在其中的更高一层的抽象应用&#xff0c;以方便开发…...

std::vector

std::vector是C标准库中一个非常强大的容器类&#xff0c;它提供了动态数组的功能。std::vector可以自动调整大小&#xff0c;提供了随机访问的能力&#xff0c;同时还支持在序列的尾部高效地添加和删除元素。 当创建一个空的std::vector对象时&#xff0c;它不分配任何内存&a…...

Java Web 之 Cookie 详解

在 JavaWeb 开发中&#xff0c;Cookie 就像网站给浏览器贴的小纸条&#xff0c;用于记录一些用户信息或状态&#xff0c;方便下次访问时识别用户身份或进行个性化服务。 也可以这么理解&#xff1a; 场景一&#xff1a;想象一下&#xff0c;你去一家咖啡店&#xff0c;店员认…...

linux系统下让.py文件开机自启动

一 创建服务文件 1、打开终端 2、切换到root用户 sudo su3、创建一个新的systemd服务文件 nano /etc/systemd/system/total_test0619.service 4、在服务文件中添加以下内容 [Unit] DescriptionRun total_test0619.py at startup[Service] Typesimple ExecStart/usr/bin/n…...

linux远程桌面:xrdp 安装失败

window 如何远程 Linux 桌面 安装xrdp yum install xrdpsystemctl start xrdp 如果找不到软件包&#xff0c;就安装epel源&#xff0c;最好改成国内镜像的 在 /etc/yum.repos.d/ 下创建epel.repo,内容如下 [epel] nameExtra Packages for Enterprise Linux 7 - $basearch …...

9.30Python基础-元组(补充)、字典、集合

Python元组&#xff08;tuple&#xff09;补充 1、元组的不可变性 元组&#xff08;tuple&#xff09;是Python中的一种内置数据类型&#xff0c;用于存储不可变的序列。虽然元组本身不可变&#xff0c;但元组内的元素如果是可变对象&#xff08;如列表&#xff09;&#xff…...

桥接模式和NET模式的区别

桥接模式和NET模式的区别 NAT模式&#xff1a; NAT&#xff1a;网络地址转换&#xff08;模式&#xff09;&#xff1a;借助宿主机来上网&#xff0c;没桥接那么麻烦&#xff0c;只用配置DNS即可。 缺点&#xff1a;扎根于宿主机&#xff0c;不能和局域网内其它真实的主机进行…...

Pigar:Python 项目的依赖管理利器

&#x1f31f; 引言 在Python项目开发过程中&#xff0c;依赖管理是一个不可忽视的环节。一个精确且易于维护的requirements.txt文件对于项目的部署和协作至关重要。今天&#xff0c;我们将介绍一款名为Pigar的自动生成requirements.txt文件的依赖管理工具&#xff0c;它通过一…...

泰勒图 ——基于相关性与标准差的多模型评价指标可视化比较-XGBoost、sklearn

1、基于相关性与标准差的多模型评价指标可视化比较 # 数据读取并分割 import pandas as pd import numpy as np import matplotlib.pyplot as plt from sklearn.model_selection import train_test_split plt.rcParams[font.family] = Times New Roman plt.rcParams[axes.unic…...

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周&#xff0c;有很多同学在写期末Java web作业时&#xff0c;运行tomcat出现乱码问题&#xff0c;经过多次解决与研究&#xff0c;我做了如下整理&#xff1a; 原因&#xff1a; IDEA本身编码与tomcat的编码与Windows编码不同导致&#xff0c;Windows 系统控制台…...

Python爬虫实战:研究MechanicalSoup库相关技术

一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...

【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15

缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下&#xff1a; struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法

树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作&#xff0c;无需更改相机配置。但是&#xff0c;一…...

FFmpeg 低延迟同屏方案

引言 在实时互动需求激增的当下&#xff0c;无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作&#xff0c;还是游戏直播的画面实时传输&#xff0c;低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架&#xff0c;凭借其灵活的编解码、数据…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂

蛋白质结合剂&#xff08;如抗体、抑制肽&#xff09;在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上&#xff0c;高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术&#xff0c;但这类方法普遍面临资源消耗巨大、研发周期冗长…...

04-初识css

一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...

EtherNet/IP转DeviceNet协议网关详解

一&#xff0c;设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络&#xff0c;本网关连接到EtherNet/IP总线中做为从站使用&#xff0c;连接到DeviceNet总线中做为从站使用。 在自动…...

.Net Framework 4/C# 关键字(非常用,持续更新...)

一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...