精华内容
下载资源
问答
  • 内存对齐,memory alignment.为了提高程序的性能,数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;然而,对齐的内存访问仅需要一次访问。内存对齐...
  • C++ 内存对齐原则及作用 C++ 内存对齐原则及作用 C++ 内存对齐原则及作用
  • C++内存对齐

    2012-05-24 15:59:30
    C++内存对齐是个看似简单,但大家经常容易犯错的地方,本文详细总结了C++内存对齐,尤其是结构体对齐方面的知识,提出了自己理论总结,希望能对读者有参考价值!
  • 内存对齐,memory alignment.为了提高程序的性能,数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;然而,对齐的内存访问仅需要一次访问。  内存...
  • C++ 内存对齐

    2021-10-30 11:08:26
    内存对齐是编译器对数据在内存放置位置的优化处理,在C++中,能够指定内存中对象位置的对齐方式,以尽可能地利用特定硬件结构的优势。一方面减少了对象所占用的内存大小,CPU也能更快地访问这些数据,另一方面考虑了...

    1、为什么需要内存对齐

    内存对齐是编译器对数据在内存放置位置的优化处理,在C++中,能够指定内存中对象位置的对齐方式,以尽可能地利用特定硬件结构的优势。一方面减少了对象所占用的内存大小,CPU也能更快地访问这些数据,另一方面考虑了不同平台的兼容性,原因如下:

    • 对于内存中的某些数据变量,如果这些变量存放位置没有对齐,那么CPU读取一个数据需要两个指令周期,而内存对齐后只需要一个,从而提高了数据访问速率。
    • c++程序可以部署在许多不同的平台中,每个平台的CPU对内存数据读取的方式都不同,有些特殊变量在不同平台下存放位置不同,如果内存没有对齐,那么可能无法寻址特殊变量,从而抛出异常。

    2、内存对齐规则

    编译器中提供了#pragma pack(n)来设定变量以n字节对齐方式。在C++中常用到两种变量,普通变量和结构体变量,对于普通变量,其对齐规则如下:

    • 如果n大于等于该变量所占用的字节数,那么偏移量必须满足默认的对齐方式
    • 如果n小于该变量的类型所占用的字节数,那么偏移量为n的倍数,不用满足默认的对齐方式

    对于结构体变量,则有

    • 首个变量距该结构体起始地址的偏移量固定为0,后面的变量根据其自身大小和#pragma pack指定的对齐单位中的较小者进行内存对齐。
    • 结构体自身也要内存对齐,根据结构体中具有最大长度的变量占用内存大小和#pragma pack指定的对齐单位中的较小者对齐。
    • 结构体作数据成员时,其地址偏移量必须为其数据成员的最大长度的整数倍,以这个长度作为其偏移地址的对齐单位。

    3、实例分析

    下面通过两个实例来应用上面的对齐规则

    实例1

    struct{
        char x;
        int y;
    }s1;

    在gcc中默认为#pragma pack(4)

    计算结构体s1所占用的内存步骤:

    • 计算sizeof(x)的结果为1
    • 计算sizeof(y)的结果为4,对齐单位为4,其偏移量(相对其所在的结构体来说)应为4的整数倍,所以y不能紧挨着x存储,中间需要填补3个内存单元,如下图所示。

    •  这样结构体s1的内存大小为8,是4的整数倍,不用补齐,最终结果就是8.

    实例2

    struct{
        int y;
        char x;
    }s2;

     现在,将结构体s1的变量定义顺序交换,如结构体s2所示,那么结构体s2所占用的内存计算步骤为:

    • 计算sizeof(y)的结果为4
    • 计算sizeof(x)的结果为1,对齐单位为1,x可以紧挨y存储
    • 这样总的大小为5,不是4的整数倍,所以需要在x之后补齐,如下图所示,最终占用内存为8.

     

    展开全文
  • 详细介绍了c++内存对齐的原因,内存是怎么对齐的
  • C/C++内存对齐

    千次阅读 2019-03-19 08:37:17
    在面试或工作中,经常会遇到内存对齐的问题。这里结合我的理解谈一谈对内存对齐的理解。 1. 为什么要内存对齐,不对齐会怎么样? 内存中存放数据是为了给CPU使用,CPU访问内存数据时会受到地址总线宽度的限制,也...

    在面试或工作中,经常会遇到内存对齐的问题。这里结合我的理解谈一谈对内存对齐的理解。

    1. 为什么要内存对齐,不对齐会怎么样?

    内存中存放数据是为了给CPU使用,CPU访问内存数据时会受到地址总线宽度的限制,也就是一次能从内存中拿多少数据到CPU(这里我们忽略CPU高速缓存)。而且,CPU从内存中获取数据时起始地址必须是地址总线宽度的倍数。

    例如:CPU地址总线是64位(bit,8字节),当一个int(4字节)存储到地址: 0x06 时,CPU如何获取这个int值?

    第一步:读取0x00~0x08  8个字节,然后保存后两个字节到 int 的前两个字节。

    第二步:读取0x08~0x0F  8个字节,然后保存前两个字节到int的后两个字节。

    图1-内存访问

    上面的例子可以看到,从内存中读取一个int到CPU中需要从内存中读取两次。这样大大降低了执行的效率,如何提升性能? 答案就是内存对齐!

    2. 内存对齐的单位是什么?

    通过上面的分析,知道内存对齐的目的是为了让CPU能一次获取到数据,从而提升性能。学过汇编会了解,CPU只能使用基本类型,char, short, int, long, float, double 等,不能使用数组或结构体等复合类型(汇编中并没有一个指令能直接存取一个struct或数组)。所以:内存对齐的单位是基本类型,目标是让CPU能一次获取到基本类型的值。

    3. 如何进行内存对齐?

    通过上面的介绍,我们可以得出:

    a. 内存对齐是指,变量地址的对齐,而不是变量大小的对齐。变量地址的对齐是指变量地址 对 变量大小求模为0。

    b. 结构体中每一个成员都要求是内存对齐的。

    c. 结构体中的数组,按数组的类型对齐。

    4. 如何计算内存对齐

    分析内存对齐,只需要记住上一个小节中:变量地址的对齐是指变量地址 对 变量大小求模为0。数组以数组本身的类型来计算,例如:char c[5] 按 char 类型大小计算对齐,double d[22] 按 double 类型大小计算对齐。

    示例程序

    运行结果

    通过这个示例,仔细想想,内存对齐就很简单了。

    展开全文
  • 主要介绍了C语言、C++内存对齐问题详解,内存对齐的问题主要存在于理解struct和union等复合结构在内存中的分布,需要的朋友可以参考下
  • C/C++ 内存对齐

    千次阅读 2018-12-16 20:33:57
    为什么要内存对齐 1.平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。  2.性能原因:数据结构(尤其是栈)应该尽...

    为什么要内存对齐

    1.平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。 
    2.性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。
     

    如何内存对齐

    首先知道相关概念:偏移地址,对齐参数,常见数据类型大小。

    偏移地址:

    内存寻址公式

    32位系统

    物理地址(就是数据存储的实际地址)=32位的段基地址+32位的偏移量

    8086

    物理地址(就是数据存储的实际地址)=16位的段基地址*16+16位的偏移量

    对齐参数:

    在windows中,VS编译器下,默认对齐数为8; 
    在Linux中,默认对齐数为4 
    设置对齐参数可在结构体struct之前加上#pragma pack(对齐数),在struct之后加上#pragma pack;便可以设置对齐参数。 

    对齐参数不能任意设置,只能是内置类型已有的字节数,如:char(1)、short(2),int(4),double(8)…不能是3,5…任意数。

    #pragma pack(4)
    struct   A
                {
                   int a;
                   char b;
                   double c;
                   char d;
                };
    #pragma pack;
    

    数据类型大小:

    在windows系统32位平台上: 
    int占4个字节 
    char占1个字节 
    float占4个字节 
    double占8个字节 

    上述structA在windows 对齐参数(8)下存放结果:
    示意图

    图参考自https://blog.csdn.net/dai_wen/article/details/78304568

    方法:

    a、从零偏移处开始,按字节大小计算,判断此偏移地址是否为该成员变量和对齐参数两者之间的最小值,即min(对齐参数,sizeof()成员); 
    b、若是,则从此处开始占用内存,大小为该类型所占字节数值,若不是,则内存向后偏移到最小值整数倍处,再开始占用空间。 
    c、按a、b、两步骤算出结构体实际所占内存时,为了方便后面类型的存储,再向后偏移一位,然后判断该地址是否是默认对齐数与该结构体中最大类型所占字节数的最小值 ,即:min(默认对齐参数,类型最大字节数)的整数倍,若是,则当前偏移地址的字节数便是结构体大小,若不是,继续向后偏移,直至为最小值整数倍为止。 
     

    求成员相对于结构体起始位置的偏移量

    使用offsetof宏来判断结构体中成员的偏移地址。使用offsetof宏需要包含stddef.h头文件,该宏定义如下:

       #define offsetof(type,menber) (size_t)&(((type*)0)->member)

    将地址0强制转换为type类型的指针,从而定位到member在结构体中偏移位置,编译器认为0是一个有效的地址,从而认为0是type指针的起始地址。 
     

    展开全文
  • struct/class/union内存对齐原则有四个: 1).数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员大小...

    原文地址:https://blog.csdn.net/chy19911123/article/details/48894579

    struct/class/union内存对齐原则有四个:

    1).数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员大小(只要该成员有子成员,比如说是数组,结构体等)的整数倍开始(比如int在32位机为4字节, 则要从4的整数倍地址开始存储),基本类型不包括struct/class/uinon。

    2).结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部"最宽基本类型成员"的整数倍地址开始存储.(struct a里存有struct b,b里有char,int ,double等元素,那b应该从8的整数倍开始存储.)。

    3).收尾工作:结构体的总大小,也就是sizeof的结果,.必须是其内部最大成员的"最宽基本类型成员"的整数倍.不足的要补齐.(基本类型不包括struct/class/uinon)。

    4).sizeof(union),以结构里面size最大元素为union的size,因为在某一时刻,union只有一个成员真正存储于该地址。

     

    实例解释:下面以class为代表

    No.1

    复制代码

    class Data
    {
        char c;
        int a;
    };
     
    cout << sizeof(Data) << endl;

    复制代码

    No.2

    复制代码

    class Data
    {
        char c;
        double a;
    };
     
    cout << sizeof(Data) << endl;

    复制代码

    显然程序No.1 输出的结果为 8    No.2 输出的结果为 16 .

    No.1最大的数据成员是4bytes,1+4=5,补齐为4的倍数,也就是8。而No.2为8bytes,1+8=9,补齐为8的倍数,也就是16。

     

    No.3

    复制代码

    class Data
    {
        char c;
        int a;
        char d;
    };
     
    cout << sizeof(Data) << endl;

    复制代码

    No.4

    复制代码

    class Data
    {
        char c;
        char d;
        int a;
    };
     
    cout << sizeof(Data) << endl;

    复制代码


    No.3运行结果为 12  No.4运行结果为 8

    class中的数据成员放入内存的时候,内存拿出一个内存块来,数据成员们排队一个一个往里放,遇到太大的,不是把自己劈成两半,能放多少放多少,而是等下一个内存块过来。这样的话,就可以理解为什么No.3,No.4两端的代码输出结果不一样了,因为左边是1+(3)+4+1+(3)=12,而右边是1+1+(2)+4=8。括号中为补齐的bytes。

     

     

    No.5

    复制代码

    class BigData
    {
        char array[33];
    };
     
    class Data
    {
        BigData bd;
        int integer;
        double d;
    };
     
    cout << sizeof(BigData) << "   " << sizeof(Data) << endl;

    复制代码

    No.6

    复制代码

    class BigData
    {
        char array[33];
    };
     
    class Data
    {
        BigData bd;
        double d;
    };
     
    cout << sizeof(BigData) << "   " << sizeof(Data) << endl;

    复制代码

    No.5和No.6运行结果均为: 48

    在默认条件下,内存对齐是以class中最大的那个基本类型为基准的,如果class中有自定义类型,则递归的取其中最大的基本类型来参与比较。在No.5和No.6中内存块一个接一个的过来接走数据成员,一直到第5块的时候,BigData里只剩1个char了,将它放入内存块中,内存块还剩7个bytes,接下来是个int(4bytes),能够放下,所以也进入第5个内存块,这时候内存块还剩3bytes,而接下来是个double(8bytes),放不下,所以要等下一个内存快到来。因此,No.5的Data的size=33+4+(3)+8=48,同理No.6应该是33+(7)+8=48。

     

    顺便提一下Union: 共用体表示几个变量共用一个内存位置,在不同的时间保存不同的数据类型和不同长度的变量。在union中,所有的共用体成员共用一个空间,并且同一时间只能储存其中一个成员变量的值。

     

    内存对齐的主要作用是:

    1、  平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。

    2、  性能原因:经过内存对齐后,CPU的内存访问速度大大提升。具体原因稍后解释。

     

    图一:

    这是普通程序员心目中的内存印象,由一个个的字节组成,而CPU并不是这么看待的。

     

    图二:

    CPU把内存当成是一块一块的,块的大小可以是2,4,8,16字节大小,因此CPU在读取内存时是一块一块进行读取的。块大小成为memory access granularity(粒度) 本人把它翻译为“内存读取粒度” 。

     

    假设CPU要读取一个int型4字节大小的数据到寄存器中,分两种情况讨论:

    1、数据从0字节开始

    2、数据从1字节开始

     

    再次假设内存读取粒度为4。

     

    图三:

    当该数据是从0字节开始时,很CPU只需读取内存一次即可把这4字节的数据完全读取到寄存器中。

        当该数据是从1字节开始时,问题变的有些复杂,此时该int型数据不是位于内存读取边界上,这就是一类内存未对齐的数据。

     

    图四:

     

    此时CPU先访问一次内存,读取0—3字节的数据进寄存器,并再次读取4—5字节的数据进寄存器,接着把0字节和6,7,8字节的数据剔除,最后合并1,2,3,4字节的数据进寄存器。对一个内存未对齐的数据进行了这么多额外的操作,大大降低了CPU性能。

        这还属于乐观情况了,上文提到内存对齐的作用之一为平台的移植原因,因为以上操作只有有部分CPU肯干,其他一部分CPU遇到未对齐边界就直接罢工了。

    展开全文
  • 主要给大家总结了关于C++面试题中结构体内存对齐计算问题的相关资料,文中通过示例代码介绍的非常详细,通过这些介绍的内容对大家在面试C++工作的时候,会有一定的参考帮助,需要的朋友们下面随着小编来一起学习学习...
  • C语言和C++都有内存对齐,当定义一个结构体时,如果不指定内存对齐方式,则会按照默认的最大元素内存对齐C++中,内存对齐用编译头指令#pragma pack(N),N代表N个字节对齐。如果N的值为零,则自动恢复原来系统内存...
  • C++中的class、struct、union首地址内存对齐到第一个数据成员字节大小的整数倍,如第一个是short(2字节)则首地址是2字节的整数倍,class、struct内存大小是对齐到最大字节的整数倍。union的大小以大的成员为准。...
  • 结构体/类内存对齐的规则 1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除; 备注:编译器在给结构体开辟空间时,首先找到结构体中最宽的基本数据类型,然后寻找内存地址能被该基本数据类型所整除的...
  • struct/class/union内存对齐原则有四个:1).数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员大小...
  • C++ 内存对齐 及 &引用是否真的节省内存的一点思考

    千次阅读 多人点赞 2020-03-24 01:06:37
    内存对齐2. 递归中的内存对齐 1. 内存对齐 通过以下语句,获取变量的占用内存打下: cout << "size of int " << sizeof(int) << endl; cout << "size of char " << sizeof(char) <...
  • c++内存对齐的规则

    2020-04-13 12:18:26
    内存对齐规则: “对齐系数”: #pragma pack(n) “对齐单位”,也叫有效对齐值 min(#pragma pack(n), 最大长度的类型) 结构体的总大小为 有效对齐值 的整数倍,如有需要编译器会在最末一个成员之后加上填充...
  • C/C++内存对齐.pdf

    2014-09-23 00:29:34
    介绍C/C++内存对齐(字节对齐)的概念以及对齐规则。通过示例代码和图示帮助理解。
  • C++内存对齐原则

    2017-07-04 21:16:43
    C++内存对齐原则 (1)在没有#pragam pack宏的情况下,struct/class/union内存对齐原则有四个:  数据成员对齐规则:结构(struct)或联合(union)的数据成员,第一个数据成员放在offset为0的位置,以后每个数据...
  • c++ 内存对齐那些事

    千次阅读 2018-09-09 18:11:16
    内存对齐介绍 目前的计算机系统中 cpu都是按照字节进行读取存储的内存数据,访问某一个变量的时候 需要在特定的地址空间中访问,此时就需要各种不同类型的变量在内存空间中按照一定的规则进行排放,而不是一个接一...
  • 背景:在任务中遇到了由于内存对齐引起的一个Double数据读取错误问题,排查很久才发现偏移地址跑了4位。 内存对齐知识整理: 1、一个对齐的例子: struct Struct1 { char FileFlag[10]; // char BuildUnit...
  • C++内存对齐总结

    2018-02-12 14:11:46
    而值得注意的是,类中非静态成员变量的大小与编译器内存对齐的设置有关。成员变量在类中的内存存储并不一定是连续的。它是按照编译器的设置,按照内存块来存储的,这个内存块大小的取值,就是内存对齐。 一、引入...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 53,088
精华内容 21,235
关键字:

c++内存对齐

c++ 订阅