精华内容
下载资源
问答
  • C++字节对齐

    2019-05-15 14:45:58
    C和C++字节对齐 文章目录C和C++字节对齐1. 什么是字节对齐2. 对齐的原因和作用3. 对齐准则4. 结果分析5. 字节对齐设置 1. 什么是字节对齐   现代计算机中,内存空间按照字节划分,理论上可以从任何起始地址访问...

    1. 什么是字节对齐

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

    2. 对齐的原因和作用

      不同硬件平台对存储空间的处理上存在很大的不同。某些平台对特定类型的数据只能从特定地址开始存取,而不允许其在内存中任意存放。但最常见的情况是,如果不按照平台要求对数据存放进行对齐,会带来存取效率上的损失。比如32位的Intel处理器通过总线访问(包括读和写)内存数据。每个总线周期从偶地址开始访问32位内存数据,内存数据以字节为单位存放。如果一个32位的数据没有存放在4字节整除的内存地址处,那么处理器就需要2个总线周期对其进行访问,显然访问效率下降很多。
      因此,通过合理的内存对齐可以提高访问效率。为使CPU能够对数据进行快速访问,数据的起始地址应具有“对齐”特性。比如4字节数据的起始地址应位于4字节边界上,即起始地址能够被4整除。
      此外,合理利用字节对齐还可以有效地节省存储空间。但要注意,在32位机中使用1字节或2字节对齐,反而会降低变量访问速度。因此不仅需要考虑处理器类型,还需要考虑编译器的类型。

    3. 对齐准则

      关于内存字节对齐,遵循以下三条对齐准则:
    (1) 数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员大小(只要该成员有子成员,比如说是数组,结构体等)的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储)。
    (2)结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储,(struct a里存有struct b,b里有char,int ,double等元素,则b应该从8的整数倍开始存储)
    (3)对齐补足:结构体的总大小,即sizeof的结果,必须是其内部最大成员的整数倍,不足的要补齐。
    32位机器上各数据类型的长度为:char为1字节、short为2字节、int为4字节、long为4字节、float为4字节、double为8字节。对于32位系统,CPU一次可以处理32bit的数据,即4字节

    字节对齐的问题主要针对的是结构体。通过以上叙述为基础,来测试以下代码,测试平台Windows7+VS2015:
    示例代码如下:

    typedef struct bb
    {
        int id;    
        double weight;    
        float height;
    }BB;
    
    typedef struct aa
    {
        char name[2];
        int id;
        double score;
        short grade; 
        BB b;
    }AA;
    
    int main()
    {
        AA a;
    
    	cout << sizeof(a) << " " << sizeof(BB) << endl;
    	cout << showbase;    //当打印整型值时显示进制
    	cout << "a  :" << hex << (int)&a << endl;
    	cout << "a.name  :" << hex << (int)&a.name << endl;
    	cout << "a.id  :" << hex << (int)&a.id << endl;
    	cout << "a.score  :" << hex << (int)&a.score << endl;
    	cout << "a.grade  :" << hex << (int)&a.grade << endl;
    	cout << "a.b  :" << hex << (int)&a.b << endl;
    	cout << "a.b.id  :" << hex << (int)&a.b.id << endl;
    	cout << "a.b.weight  :" << hex << (int)&a.b.weight << endl;
    	cout << "a.b.height  :" << hex << (int)&a.b.height << endl;
    
    	cout << noshowbase;    //恢复流状态
    
    	getchar();
    	return 0;
    }
    

    测试结果如下:

    AA中不带结构体BB AA中带结构体BB
    结果 不带结构体 带结构体

    4. 结果分析

      在当前32位系统平台下,无论AA中是否带结构体BB时,a.name的地址始终是从offset为0的地方开始的,符合原则1
      当AA中不带结构体BB时,此时计算内存大小为:0xd4 - 0xc4 = 0x10,即16字节,加上short grade本身的2字节,此时总共是18字节,与实际打印的24字节不相符,根据原则3,AA里面最大成员为8字节的double型,因此这里在short grade的地址后面偏移2个字节(short的大小),又补充了6字节的空间,最后加起来就是24字节。
      当AA中带结构体BB时,根据原则2,BB中是按照double的大小来存储的,因此BB的大小是24,根据打印的结果0xfc - 0xec = 0x10,即16字节,加上变量所占的8字节,刚好24字节。

    5. 字节对齐设置

      在编码时,可以使用指令动态修改默认的字节对齐大小:#pragma pack(n)
    例如:在上述代码前加一句#pragma pack(1),其结果输出为32 16
    bb是4+8+4=16,aa是2+4+8+2+16=32。#pragma pack(1)告诉编译器,所有的对齐都按照1的倍数对齐。#pragma pack(2)告诉编译器,所有的对齐都按照2的倍数对齐,在上述程序中将char name[2]改为char name[1],可以看出明显的区别,按1对齐是输出31,按2对齐是输出32。
    经测试,VS2015编译器默认是#pragma pack(8)。

    参考资料:

    展开全文
  • C++ 字节对齐

    2020-06-03 23:32:42
    字节对齐概念字节对齐对齐准则示例代码 概念 alignas:对齐要求即字节对齐,指定某个类型是几字节对齐。 alignof:查询类型的对齐要求 字节对齐 内存中是按照字节来划分存储空间的,理论上讲数据存储在内存上时,也...

    概念

    alignas:对齐要求即字节对齐,指定某个类型是几字节对齐。
    alignof:查询类型的对齐要求

    字节对齐

    内存中是按照字节来划分存储空间的,理论上讲数据存储在内存上时,也会是按照字节顺序进行排列,但是CPU在访问内存数据时,为了提高效率通常会按照自身位数对数据进行存取。如32位的CPU,访问内存是会一次性获取到32bit数据,如果一个32位的数据没有放在被4字节整除的地址处时,此时CPU需要读取两次才可以获取到该数据,显然是效率打折了。
    但是有时在嵌入式开发过程中,为了节省资源,方便处理字节流的数据,往往会采用一字节对齐的方式。

    对齐准则

    1. 数据类型自身的对齐值:
    类型 对齐值
    char 1
    short 2
    int 4
    float 4
    long 8
    double 8
    1. 结构体或者类的自身对齐值:其成员中自身对齐值最大的那个值。
        struct testStr
        {
            char data;
            int len;
        } ;
       std::cout << "alignof(struct):" << alignof(struct testStr) << std::endl;
    

    结构体testStr的对齐值是4,按照int类型进行对齐。

    1. 指定对齐值:#pragma pack (value)时或者alignas(value)指定对齐值value。
    #pragma pack(1)
        struct testPackOne
        {
            char data;
            int len;
        } testPackOneData;
        std::cout << "alignof(struct):" << alignof(struct testPackOne) << std::endl;
    #pragma pack()
    
        struct alignas(8) testAlignas
        {
            char data;
            int len;
        } testAlignasData;
        std::cout << "alignof(struct testAlignas):" << alignof(struct testAlignas) << std::endl;
    

    结构体testPackOne对齐值是1,按照指定的value对齐。
    结构体PackOne对齐值是8,按照指定的value对齐,⚠️注意:alignas对齐要求必须大于等于该类型内最大的对齐值。修改为以下代码时编译器保存:

    	struct alignas(1) testAlignas
        {
            char data;
            int len;
        } testAlignasData;
        std::cout << "alignof(struct testAlignas):" << alignof(struct testAlignas) << std::endl;
    

    错误信息:

    alignas.cpp:46:12: error: requested alignment is less than minimum alignment of 4 for type 'testAlignas'
      struct alignas(1) testAlignas
             ^
    1 error generated.
    
    1. 数据成员、结构体和类的有效对齐值:自身对齐值和指定对齐值中小的那个值。

    示例代码

    示例代码

    未完待续…

    展开全文
  • VS C++字节对齐方式

    2020-12-18 23:56:48
    VS C++字节对齐方式
  • c++字节对齐

    2018-12-27 18:06:29
    如果编辑器对数据存放做了对齐,而我们不了解的话,常常会对一些问题感到迷惑。最常见的就是struct数据结构的sizeof结果,比如以下程序: #include &lt;stdio.h&gt; void main(){ struct A{ char ...

    参考文章:

    https://www.cnblogs.com/ningvsban/p/3940153.html

     

    如果编辑器对数据存放做了对齐,而我们不了解的话,常常会对一些问题感到迷惑。最常见的就是struct数据结构的sizeof结果,比如以下程序:

    #include <stdio.h>
    
    void main(){
    
        struct A{
            char a;
            short b;
            int c;
        };
    
        printf( "size of struct A = %d \n", sizeof(struct A) );
    
    }

    输出结果为:8字节。

    如果我们将结构体中的变量声明位置稍加改动(并不改变变量本身),请再看以下程序:

    #include <stdio.h>
    
    void main(){
    
        struct A{
            short b;
            int c;
            char a;
        };
    
        printf( "size of struct A = %d \n", sizeof(struct A) );
    
    }

    输出结果为:12字节。

    问题出来了,他们都是同一个结构体,为什么占用的内存大小不同呢?为此,我们需要对对齐算法有所了解。

     

    对齐算法

    由于各个平台和编译器的不同,现以32位,vc++6.0系统为例,来讨论编译器对struct数据结构中的各成员如何进行对齐的。

    首先,我们给出四个概念:

    1)数据类型自身的对齐值:就是基本数据类型的自身对齐值,比如char类型的自身对齐值为1字节,int类型的自身对齐值为4字节。

    2)指定对齐值:预编译命令#pragma pack (value)指定的对齐值value。

    3)结构体或者类的自身对齐值:其成员中自身对齐值最大的那个值,比如以上的struct A的对齐值为4。

    4)数据成员、结构体和类的有效对齐值:自身对齐值和指定对齐值中较小的那个值。

     

    设结构体如下定义:

    struct A{
        char a;
        short b;
        int c;
    };

    a是char型数据,占用1字节内存;short型数据,占用2字节内存;int型数据,占用4字节内存。因此,结构体A的自身对齐值为4。于是,a和b要组成4个字节,以便与c的4个字节对齐。而a只有1个字节,a与b之间便空了一个字节。我们知道,结构体类型数据是按顺序存储结构一个接一个向后排列的,于是其存储方式为:

    其中空白方格无数据,是浪费的内存空间,共占用8字节内存。

    实际上,为了更加明显地表示“对齐”,我们可以将以上结构想象为以下的行排列:

     

    对于另一个结构体定义:

    struct A{
            short b;
            int c;
            char a;
        };

    其内存存储方式为:

     

    同样把它想象成行排列:

    可见,浪费的空间更多。

    其实,除了结构体之外,整个程序在给每个变量进行内存分配时都会遵循对齐机制,也都会产生内存空间的浪费。但我们要知道,这种浪费是值得的,因为它换来的是效率的提高。

    以上分析都是建立在程序默认的对齐值基础之上的,我们可以通过添加预定义命令#pragma pack(value)来对对齐值进行自定义,比如#pragma pack(1),对齐值变为1,此时内存紧凑,不会出现内存浪费,但效率降低了。效率之所以降低,是因为:如果存在更大字节数的变量时(比1大),比如int类型,需要进行多次读周期才能将一个int数据拼凑起来。

     

     

    这篇文章超级超级超级详细:

    https://www.cnblogs.com/clover-toeic/p/3853132.html

     

     

     

     

     

     

     

     

     

     

    展开全文
  • C++ 字节对齐规则

    2020-09-21 22:30:22
    C++ 字节对齐规则 规则 遵循结构体对齐(成员大小向各参数中较小的对齐,结构体总长度要是所有对齐参数的整数倍) 空类大小为1:地址唯一,相当于占位符 成员函数中有虚函数(要有一个虚表指针),普通成员函数不占...

    C++ 字节对齐规则

    规则

    • 遵循结构体对齐(成员大小向各参数中较小的对齐,结构体总长度要是所有对齐参数的整数倍)
    • 空类大小为1:地址唯一,相当于占位符
    • 成员函数中有虚函数(要有一个虚表指针),普通成员函数不占内存
    • 静态成员变量不占内存(存储在全局变量区,类共享)

    样例

    所有代码都是在VS的编译结果

    #include<iostream>
    #include<algorithm>
    using namespace std;
    class a
    {
        int i;
        char c, d, f;
    };
    int main()
    {
        a tmp;
        cout << sizeof(tmp) << endl; // 8
        return 0;
    }
    

    说明 因为三个char是连续的地址空间,只需要对齐为4

    #include<iostream>
    #include<algorithm>
    using namespace std;
    class a
    {
        char c;
        int i;
        char d, f;
    };
    int main()
    {
        a tmp;
        cout << sizeof(tmp) << endl; // 12
        return 0;
    }
    

    说明 由于第一个char提前,导致需要和后续的int进行对齐

    #include<iostream>
    #include<algorithm>
    using namespace std;
    class a
    {
        int i;
        char *c;
        short d;
        virtual void test()
        {}
    };
    int main()
    {
        a tmp;
        cout << sizeof(tmp) << endl;
        return 0;
    }
    

    说明 加入了虚函数,需要有虚表指针,因此相应的大小在VS下是16(因为指针大小为4字节)。但是,在DEV C++软件下的编译结果是24(因为,64位系统,指针大小是8字节)。因此,编译器也会影响大小的判定。

    展开全文
  • c/c++字节对齐

    2017-07-14 18:28:33
    c/c++字节对齐问题
  • c++ 字节对齐

    2010-01-05 10:46:28
    sizeof() &amp; #pragma 结构体的sizeof ...问sizeof(s1)等于多少聪明的你开始思考了,char占1个字节,int占4个字节,那么 加起来就应该是5。是这样吗你在你机器上试过了吗也许你是对的...
  • 关于C++字节对齐

    2020-08-26 11:33:33
    关于C++字节对齐 大神博客1:介绍的简单明了,例子很容易理解 大神博客2:从地址层面介绍,例子很容易理解 偏移量:变量的地址相对于起始地址的偏移量 普通变量的偏移量必须为下面的倍数 sizeof(char) :1 sizeof...
  • C++字节对齐问题

    2014-04-01 22:46:17
    C++字节对齐问题
  • C/C++字节对齐

    2018-05-16 08:43:41
    仔细讨论 C/C++ 字节对齐问题字节对齐的原因 为了提高 CPU 的存储速度,编译器会对 struct 和 union的存储进行优化,即进行字节对齐。对齐方式 对于 struct 或 union 中的 struct 或者 union 来说,它们的字节对齐...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,649
精华内容 659
关键字:

c++字节对齐

c++ 订阅