[C++] 内存对齐完整解读

devtools/2024/9/25 5:30:09/

说明:内存对齐是指按照特定的规则来组织数据在内存中的排列方式,以提高内存访问的效率。在计算机系统中,内存对齐可以减少CPU访问内存时所需的总周期数,因为许多硬件平台只能从某些特定地址(如2的幂次方)开始读取数据。内存对齐是确保数据的地址是其大小的倍数,这通常可以提高程序的性能,特别是在需要频繁访问数据的情况下。

接下来我们看看到底为什么引入 内存对齐。

1 为什么引入内存对齐?

C++中引入内存对齐的概念主要是出于以下几个原因:

  • 硬件效率:许多CPU在硬件层面对内存访问进行了优化,它们可以从特定对齐的内存地址更高效地读取数据。未对齐的内存访问可能会导致性能下降,甚至在某些架构上导致异常。
  • 兼容性:内存对齐是许多系统硬件的要求。不正确的对齐可能会导致未定义行为,包括程序崩溃或数据损坏。C++通过内存对齐确保了跨平台兼容性和程序的可移植性。
  • 内存访问优化:内存对齐可以减少CPU访问内存时所需的总周期数。这是因为对齐的数据可以直接被硬件高效地读取,而不需要额外的内存访问操作。
  • 缓存利用:内存系统通常以缓存行(cache line)为单位存储数据。内存对齐可以提高缓存的利用率,因为对齐的数据更有可能被完整地存储在单个缓存行中。
  • 多平台支持:不同的硬件平台可能有不同的内存对齐要求。C++的内存对齐特性允许开发者编写能够在多种架构上运行而无需修改的代码。
  • 接口与ABI(应用二进制接口):内存对齐对于维护与C语言及其它语言的兼容性至关重要。C++类和结构体的内存布局需要与C语言结构体保持一致,以确保可以轻松地与C语言库进行交互。
  • 避免字节填充:在没有明确对齐要求的情况下,编译器可能会在结构体中插入额外的字节填充(padding),以满足成员的对齐要求。这可能导致不必要的内存浪费。显式内存对齐可以减少这种填充,节省内存空间。
  • 模板元编程:在模板编程中,特别是涉及复杂数据结构时,显式控制内存对齐可以避免不必要的内存浪费,并提高程序性能。
  • 安全性:内存对齐有助于避免未定义行为。通过确保数据按照特定的规则对齐,C++可以减少因内存访问错误导致的安全问题。
  • 语言特性的完善:内存对齐是C++追求成为一个全面、高效和安全的语言的一部分。C++11及后续标准引入了alignasalignof等特性,以提供一种标准的方式来处理内存对齐问题。

总的来说,它对于提高程序性能、确保程序的安全性和可移植性、以及优化内存使用都至关重要。

2 C++ 内存对齐方法总结

在C++11之前,编译器提供了一些特定的扩展或者特定的编译器指令来实现内存对齐,这些指令通常是编译器特定的。

2.1 C++11之前常用内存对齐方法总结

在MSVC中,可以使用__declspec(align(n))来指定变量或类型的对齐字节数。参考代码如下:

// 指定该结构体以16字节对齐
__declspec(align(16)) struct MyStruct {char a;int b;double c;
};

在GCC和Clang中,可以使用__attribute__((aligned(n)))来指定对齐。参考代码如下:

// 指定该结构体以16字节对齐
struct MyStruct {char a;int b;double c;
} __attribute__((aligned(16)));

虽然C++11之前,C++标准并未提供内存对齐的关键字,但C语言(从C99开始)提供了_Alignas_Alignof关键字,这些可以在C++代码中使用。参考代码如下:

// 指定该结构体以16字节对齐
typedef struct MyStruct {char a;int b;double c;
} _Alignas(16) MyStruct;

一些旧的编译器使用预处理器指令来控制对齐,如#pragma pack。参考代码如下:

#pragma pack(push, 1)
struct MyStruct {char a;int b;double c;
};
#pragma pack(pop)

在这个例子中,#pragma pack(push, 1)指示编译器按照1字节边界对齐,禁用任何额外的对齐填充。#pragma pack(pop)则将对齐设置恢复到之前的设置。

注意:这些方法都是编译器特定的,可能不具有跨编译器的可移植性。C++11引入的alignasalignof提供了一种标准的方式来处理内存对齐,这在不同的编译器和平台上都能保证一致性。

2.2 C++11标准的内存对齐解读

C++11标准引入的alignasalignof关键字解读具体如下:

  • alignas:用于指定变量或类型的内存对齐字节数。
  • alignof:用于查询变量或类型的内存对齐字节数。

下面是一个使用alignasalignof的简单示例代码:

#include <iostream>
#include <type_traits>// 定义一个结构体,使用alignas指定其对齐字节数为16
struct alignas(16) MyStruct {char a; int b;double c;
};int main() {// 创建MyStruct类型的变量MyStruct ms;// 使用alignof查询MyStruct的对齐字节数并输出,这里是16,因为之前定义为16//如果定义为alignas(4) ,即4字节对齐,则为4.std::cout << "Alignment of MyStruct is: " << alignof(MyStruct) << " bytes" << std::endl;// 使用sizeof查询MyStruct的大小并输出,这里是16std::cout << "Size of MyStruct is: " << sizeof(MyStruct) << " bytes" << std::endl;return 0;
}

这里我们定义了一个结构体MyStruct,并使用alignas(16)指定其对齐字节数为16。然后在main函数中,我们创建了一个MyStruct类型的变量ms,并使用alignofsizeof运算符分别查询并输出了MyStruct的对齐字节数和大小。

输出结果将显示MyStruct的对齐字节数为16,大小根据成员变量的大小和对齐要求进行调整。具体如下:

//以下padding表示编译器添加的填充字节
struct alignas(16) MyStruct {char a; //1+3paddingint b;  //4+0paddingdouble c;//8+0padding
};
//共计:1+(3)+4+8=16字节

由于我们指定了16字节的对齐,即使成员变量的实际大小之和小于16字节,编译器也可能会增加填充字节以达到16字节的对齐要求,从而提高内存访问效率。


http://www.ppmy.cn/devtools/11725.html

相关文章

Android系统native进程之我是installd进程

用心坚持输出易读、有趣、有深度、体系化的技术文章 本文摘要 这是Android系统进程系列的第五篇文章&#xff0c;本文同样以自述的方式带您了解installd进程&#xff0c;通过本文您将了解到linstalld进程为啥存在&#xff1f;以及在安装/卸载apk中发挥了哪些作用。&#xff0…

Qotom低功耗赛扬J4125 X86工控迷你电脑主板

Qotom X86 Mini PC主板低功耗赛扬J4125处理器itx主板适用于网络安全、工业控制、物联网等 • Intel Celeron J4125 Gemini Lake 处理器工业 PC 主板 • 英特尔高清显卡 600 • 1 x 高清视频、1 x 显示端口、1 x VGA&#xff08;接头&#xff09; • 4 个 USB 3.0、2 个 USB 2.…

【AI面试】工作和面试过程中,经常遇到的其他问题汇总一(持续更新)

在与面试官在面对面进行交流的过程中,面试官不仅仅会针对简历中记录的内容进行深入的了解,还会进行一些发散性的提问。 目前也就很明显,就是要看看对方: 对于常见的问题是如何思考的?有没有在持续性的学习本领域的新知识?对于不知道的问题,是如何思考的?迁移能力咋样。…

基于sfunction builder的c-sfunction编写——自定义函数编写

目录 前言 1、sfunction builder自定义函数编写方法一 2、sfunction builder自定义函数编写方法二 3.总结

在 Kubernetes 1.24 中使用 Docker:配置与应用指南

在 Kubernetes 1.24 中使用 Docker&#xff1a;配置与应用指南 引言 随着 Kubernetes 社区对容器运行时接口&#xff08;CRI&#xff09;的标准化推进&#xff0c;Docker 原生支持在 Kubernetes 1.24 版本中被弃用。然而&#xff0c;许多开发者和组织仍希望继续使用 Docker。…

本地生活服务平台都有哪些,靠谱吗?

随着本地生活服务的发展潜力和盈利方式被不断挖掘&#xff0c;越来越多的人开始发现其中所蕴含着的巨大商机&#xff0c;大家所熟悉的抖音、小红书和支付宝等平台也纷纷上线了本地生活板块&#xff0c;再次印证了其前景的广阔。在此背景下&#xff0c;普通人想要趁势入局分一杯…

GPT国内能用吗

2022年11月&#xff0c;Open AI发布ChatGPT&#xff0c;ChatGPT展现了大型语模型在自然语言处理方面的惊人进步&#xff0c;其生成文本的流畅度和连贯性令人印象深刻&#xff0c;为AI应用打开了新的可能性。 ChatGPT的出现推动了AI技术在各个领域的应用&#xff0c;例如&#x…

java websocket服务端丢消息

前提&#xff1a;客户端和服务端基于websocket进行交互&#xff0c;客户端每隔8s发送心跳&#xff0c;服务端检测心跳&#xff0c;超过三分钟没收到会关闭session。   现象&#xff1a;客户端日志记录发送了心跳消息&#xff0c;服务端没收到心跳&#xff0c;超时后服务端关闭…