自学内容网 自学内容网

C++ 编程基础(7)内存模型 | 7.2、内存对齐


前言:

在C++编程中,内存对齐是一种重要的机制,它确保数据在内存中的存储地址满足特定的规则。这种机制对于提高程序的运行效率和增强程序的可移植性至关重要。本文将对C++中的内存对齐机制进行详细介绍。

一、内存对齐

1、什么是内存对齐?

计算机中的内存是按字节(byte)划分的,从理论上讲对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特定的内存地址访问,这就需要各种类型的数据按照一定的规则在内存空间上排序,而不是顺序的一个接一个的排放,这就是内存对齐。

2、为什么要进行内存对齐?

  • 性能优化: CPU是以块为单位从内存读取数据,块的大小可以是2,4,8,16字节大小。经过内存对齐后,CPU的内存访问速度大大提升。例如:CPU要读取一个int型4字节大小的数据到寄存器中,分两种情况讨论:
    • 情况一: 数据从0字节开始,CPU只需读取内存一次即可回去到这4字节的数据。
    • 情况二: 当该数据是从1字节开始时,问题变的有些复杂,此时该int型数据不是位于内存读取边界上,这就是一类内存未对齐的数据。此时CPU先访问一次内存,读取[0] - [3]字节的数据进寄存器,并再次读取[4] - [7]字节的数据进寄存器,接着把0字节和5、6、7字节的数据剔除,最后合并1、2、3、4字节的数据进寄存器。对一个内存未对齐的数据进行了这么多额外的操作,大大降低了CPU性能。
  • 硬件要求: 不是所有的硬件平台都能访问任意地址上的任意数据的,某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。

3、内存对齐相关概念

3.1、自身对齐值

自身对齐值(Alignment Requirement)是指一个数据类型在内存中必须满足的对齐要求。具体来说,对于某种类型的数据,其起始地址必须是该类型大小的整数倍。

  • 基础数据类型自身对齐值: 对基础数据类型(例如:intdouble)来说,自身对齐值就是它们占用内存的大小。

  • structclass的自身对齐值: 其成员中自身对齐值最大的那个值。例如:自定义Data类型,成员中最大的对齐值是8,那Data类型的对齐值就是8、Data对象的存储起始位置是8的整数倍。

    struct Data{
        char c;
        int a;
        double d;
    };
    

3.2、指定对齐值

#pragma pack是编译器指令,用于指定结构体成员的对齐方式。默认情况下,编译器会根据目标平台和数据类型自动选择对齐方式,但有时需要手动调整以满足特定需求。

3.3、有效对齐值

自身对齐值和指定对齐值中小的那个值。例如:

#include <iostream>
using namespace std;

#pragma pack(4)
struct T{
    char a;
    short b;
    char c;
};

#pragma pack()
int main()
{
    cout << sizeof(T) << endl;  // 输出结果:6
    return 0;
}

4、内存对齐基本规则

在C++中,内存对齐主要遵循以下规则:

数据成员对齐规则:

  • 结构体(或联合)的第一个数据成员放在偏移量为0的地方。
  • 从第二个数据成员开始,每个成员存储的起始位置要从该成员大小(或成员的子成员大小,只要该成员有子成员,如数组、结构体等)的整数倍开始。

结构体(或联合)的整体对齐规则:

  • 结构体的总大小必须按照指定对齐系数和结构体最大数据成员长度中较小的那个进行整体对齐。
  • 如果结构体中各成员按规则排列后,总大小不是最大成员长度的整数倍,则需要进行补齐。

结构体作为成员的对齐规则:

  • 如果一个结构里有某些结构体成员,那么这个结构体成员要从其内部最大基本类型成员的整数倍地址开始存储。
  • 结构体的整体大小为内部最大成员的最宽基本类型成员的整数倍。

C++中的内存对齐机制是一种重要的优化手段,它可以提高程序的运行效率和增强程序的可移植性。在编写C++程序时,需要充分了解内存对齐的规则和实现方法,并合理使用这些技术来优化程序性能。


原文地址:https://blog.csdn.net/cloud323/article/details/143787185

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!