精华内容
下载资源
问答
  • struct字节对齐问题

    2017-12-04 10:02:57
    C语言项目开发过程中发现其他模块发给自己模块的消息长度与自己代码sizeof(struct)不一致,经过定位分析发现两边struct字节对齐方式不一致,C语言中默认为四字节对齐,如果struct字节不足4的倍数,则以4的倍数为...

    C语言项目开发过程中发现其他模块发给自己模块的消息长度与自己代码sizeof(struct)不一致,经过定位分析发现两边struct字节对齐方式不一致,C语言中默认为四字节对齐,如果struct字节不足4的倍数,则以4的倍数为sizeof最后的大小

    例如:

    struct a{

    int b;

    char c;

    }a;

    此时sizeof(a)则为8个字节,实际需要计算为5个字节,这时需要在struct头文件中设置1字节对齐,解决问题

    #param pack(1)

    ..... //struct defined

    #param pack()


    后续撰写项目测试用例,又发现测试用例sizeof(a)与代码实际sizeof不一致,测试框架为C++,默认字节对齐方式也是四字节,此时需要设置测试框架的字节对齐方式为1字节,修改相应的头文件

    #param once  //头文件开头

    ... //functions defined


    #param pack(push, 1)

    ...//struct defined

    #param pack(pop, 1)


    ....




    展开全文
  • 三步解决C语言中struct字节对齐问题

    万次阅读 多人点赞 2018-08-01 23:03:39
    直入主题,要判断一个结构体所占的空间大小,大体来说分三步走: ... Linux 32位 默认4字节对齐,64位默认8字节对齐 (2)结构体最大成员(基本数据类型变量) (3)预编译指令#pragma pack(n)手动设置 n--只能...

    直入主题,要判断一个结构体所占的空间大小,大体来说分三步走:

    1.先确定实际对齐单位,其由以下三个因素决定

        (1) CPU周期

        WIN  vs  qt  默认8字节对齐

        Linux 32位 默认4字节对齐,64位默认8字节对齐

        (2) 结构体最大成员(基本数据类型变量)

        (3) 预编译指令#pragma pack(n)手动设置     n--只能填1 2 4 8 16

        上面三者取最小的,就是实际对齐单位(这里的“实际对齐单位”是我为了方便区分随便取的概念)

    2.除结构体的第一个成员外,其他所有的成员的地址相对于结构体地址(即它首个成员的地址)的偏移量必须为实际对齐单位或自身大小的整数倍(取两者中小的那个)

    3.结构体的整体大小必须为实际对齐单位的整数倍。

    上面三步即是万能公式,下面看实际例子(linux 64系统下):

    1.

     

    上面nums中,没有手动设置对齐单位,linux64系统的默认对齐单位是8字节,结构体nums的最大成员double d占8个字节,故实际对齐字节是二者最小,即8字节。

    char a放在结构体的起始地址;

    short b占2个字节,2小于实际对齐字节8,故b的起始地址相对于a的起始地址的偏移量须为2的整数倍个字节;

    int c占4个字节,4小于实际对齐字节8,故c 起始地址相对于a的起始地址的偏移量须为4的整数倍个字节;

    double d占8个字节,8与实际对齐字节8相等,故d的起始地址相对于a的起始地址的偏移量须为8的整数倍个字节;

    所以nums所占空间如下:    1(a)+1(浪费的空间,由b的起始地址决定这1字节必须腾出)+2(b)+4(c)+8(d)=16个字节

     

    2.在上面结构体最后添加一个char数组,再看情况:

    到成员double d为止,结构体nums占的空间是16,上面已经分析过,然后后面是一个char型数组,数组的类型是char[13],并不是基本数据类型,这里仍然当做13个char型变量来处理,char占1个字节,小于实际对齐字节8,所以这13个char型变量可以直接挨着double d后面放(最后结果看起来也就相当于整个数组挨着double d放置);所以总的空间情况是:1(a)+1(浪费空间)+2(b)+4(c)+8(d)+13(arr)=29;但29并不满足上面三步走的最后一步:“整个结构体的大小必须是实际对齐单位的整数倍”,所以29+3(浪费空间)=32,所以最后nums的空间情况是1(a)+1(浪费空间)+2(b)+4(c)+8(d)+13(arr)+3(浪费空间)=32字节

    另外结构体嵌套结构体的字节对齐和上面原理一样,唯一要注意的是子结构体的起始地址与母结构体的起地址之间的距离必须是子结构体最大成员或者实际对齐单位(还是取两者小的那个)的整数倍。

    输出结果:

    展开全文
  • struct 字节对齐详解

    千次阅读 2015-11-18 11:42:44
    什么是字节对齐,为什么要对齐?  现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特 定的内存地址访问,这就...

    一.什么是字节对齐,为什么要对齐?

        现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特 定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。
        对齐的作用和原因:各个硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型的数据只能从某些特定地址开始存取。比如有些架构的CPU在访问 一个没有进行对齐的变量的时候会发生错误,那么在这种架构下编程必须保证字节对齐.其他平台可能没有这种情况,但是最常见的是如果不按照适合其平台要求对 数据存放进行对齐,会在存取效率上带来损失。比如有些平台每次读都是从偶地址开始,如果一个int型(假设为32位系统)如果存放在偶地址开始的地方,那 么一个读周期就可以读出这32bit,而如果存放在奇地址开始的地方,就需要2个读周期,并对两次读出的结果的高低字节进行拼凑才能得到该32bit数 据。显然在读取效率上下降很多。

    二.字节对齐对程序的影响:

    先让我们看几个例子吧(32bit,x86环境,gcc编译器):
    设结构体如下定义:
    struct A
    {
        int a;
        char b;
        short c;
    };
    struct B
    {
        char b;
        int a;
        short c;
    };
    现在已知32位机器上各种数据类型的长度如下:
    char:1(有符号无符号同)    
    short:2(有符号无符号同)    
    int:4(有符号无符号同)    
    long:4(有符号无符号同)    
    float:4     double:8
    那么上面两个结构大小如何呢?
    结果是:
    sizeof(strcut A)值为8
    sizeof(struct B)的值却是12

    结构体A中包含了4字节长度的int一个,1字节长度的char一个和2字节长度的short型数据一个,B也一样;按理说A,B大小应该都是7字节。
    之所以出现上面的结果是因为编译器要对数据成员在空间上进行对齐。上面是按照编译器的默认设置进行对齐的结果,那么我们是不是可以改变编译器的这种默认对齐设置呢,当然可以.例如:
    #pragma pack (2) /*指定按2字节对齐*/
    struct C
    {
        char b;
        int a;
        short c;
    };
    #pragma pack () /*取消指定对齐,恢复缺省对齐*/
    sizeof(struct C)值是8。
    修改对齐值为1:
    #pragma pack (1) /*指定按1字节对齐*/
    struct D
    {
        char b;
        int a;
        short c;
    };
    #pragma pack () /*取消指定对齐,恢复缺省对齐*/
    sizeof(struct D)值为7。
    后面我们再讲解#pragma pack()的作用.

    三.编译器是按照什么样的原则进行对齐的?

        先让我们看四个重要的基本概念:
    1.数据类型自身的对齐值:
    对于char型数据,其自身对齐值为1,对于short型为2,对于int,float,double类型,其自身对齐值为4,单位字节。
    2.结构体或者类的自身对齐值:其成员中自身对齐值最大的那个值。
    3.指定对齐值:#pragma pack (value)时的指定对齐值value。
    4.数据成员、结构体和类的有效对齐值:自身对齐值和指定对齐值中小的那个值。
    有了这些值,我们就可以很方便的来讨论具体数据结构的成员和其自身的对齐方式。有效对齐值N是最终用来决定数据存放地址方式的值,最重要。有效对齐N,就是 表示“对齐在N上”,也就是说该数据的"存放起始地址%N=0".而数据结构中的数据变量都是按定义的先后顺序来排放的。第一个数据变量的起始地址就是数 据结构的起始地址。结构体的成员变量要对齐排放,结构体本身也要根据自身的有效对齐值圆整(就是结构体成员变量占用总长度需要是对结构体有效对齐值的整数倍,结合下面例子理解)。这样就不难理解上面的几个例子的值了。
    例子分析:
    分析例子B;
    struct B
    {
        char b;
        int a;
        short c;
    };
    假 设B从地址空间0x0000开始排放。该例子中没有定义指定对齐值,在笔者环境下,该值默认为4。第一个成员变量b的自身对齐值是1,比指定或者默认指定 对齐值4小,所以其有效对齐值为1,所以其存放地址0x0000符合0x0000%1=0.第二个成员变量a,其自身对齐值为4,所以有效对齐值也为4, 所以只能存放在起始地址为0x0004到0x0007这四个连续的字节空间中,复核0x0004%4=0,且紧靠第一个变量。第三个变量c,自身对齐值为 2,所以有效对齐值也是2,可以存放在0x0008到0x0009这两个字节空间中,符合0x0008%2=0。所以从0x0000到0x0009存放的 都是B内容。再看数据结构B的自身对齐值为其变量中最大对齐值(这里是b)所以就是4,所以结构体的有效对齐值也是4。根据结构体圆整的要求, 0x0009到0x0000=10字节,(10+2)%4=0。所以0x0000A到0x000B也为结构体B所占用。故B从0x0000到0x000B 共有12个字节,sizeof(struct B)=12;其实如果就这一个就来说它已将满足字节对齐了, 因为它的起始地址是0,因此肯定是对齐的,之所以在后面补充2个字节,是因为编译器为了实现结构数组的存取效率,试想如果我们定义了一个结构B的数组,那 么第一个结构起始地址是0没有问题,但是第二个结构呢?按照数组的定义,数组中所有元素都是紧挨着的,如果我们不把结构的大小补充为4的整数倍,那么下一 个结构的起始地址将是0x0000A,这显然不能满足结构的地址对齐了,因此我们要把结构补充成有效对齐大小的整数倍.其实诸如:对于char型数据,其 自身对齐值为1,对于short型为2,对于int,float,double类型,其自身对齐值为4,这些已有类型的自身对齐值也是基于数组考虑的,只 是因为这些类型的长度已知了,所以他们的自身对齐值也就已知了.
    同理,分析上面例子C:
    #pragma pack (2) /*指定按2字节对齐*/
    struct C
    {
        char b;
        int a;
        short c;
    };
    #pragma pack () /*取消指定对齐,恢复缺省对齐*/
    第 一个变量b的自身对齐值为1,指定对齐值为2,所以,其有效对齐值为1,假设C从0x0000开始,那么b存放在0x0000,符合0x0000%1= 0;第二个变量,自身对齐值为4,指定对齐值为2,所以有效对齐值为2,所以顺序存放在0x0002、0x0003、0x0004、0x0005四个连续 字节中,符合0x0002%2=0。第三个变量c的自身对齐值为2,所以有效对齐值为2,顺序存放
    在0x0006、0x0007中,符合 0x0006%2=0。所以从0x0000到0x00007共八字节存放的是C的变量。又C的自身对齐值为4,所以C的有效对齐值为2。又8%2=0,C 只占用0x0000到0x0007的八个字节。所以sizeof(struct C)=8.

    四.如何修改编译器的默认对齐值?

    1.在VC IDE中,可以这样修改:[Project]|[Settings],c/c++选项卡Category的Code Generation选项的Struct Member Alignment中修改,默认是8字节。
    2.在编码时,可以这样动态修改:#pragma pack .注意:是pragma而不是progma.

    五.针对字节对齐,我们在编程中如何考虑?

        如果在编程的时候要考虑节约空间的话,那么我们只需要假定结构的首地址是0,然后各个变量按照上面的原则进行排列即可,基本的原则就是把结构中的变量按照 类型大小从小到大声明,尽量减少中间的填补空间.还有一种就是为了以空间换取时间的效率,我们显示的进行填补空间进行对齐,比如:有一种使用空间换时间做 法是显式的插入reserved成员:
             struct A{
               char a;
               char reserved[3];//使用空间换时间
               int b;
    }

    reserved成员对我们的程序没有什么意义,它只是起到填补空间以达到字节对齐的目的,当然即使不加这个成员通常编译器也会给我们自动填补对齐,我们自己加上它只是起到显式的提醒作用.

    六.字节对齐可能带来的隐患:

        代码中关于对齐的隐患,很多是隐式的。比如在强制类型转换的时候。例如:
    unsigned int i = 0x12345678;
    unsigned char *p=NULL;
    unsigned short *p1=NULL;

    p=&i;
    *p=0x00;
    p1=(unsigned short *)(p+1);
    *p1=0x0000;
    最后两句代码,从奇数边界去访问unsignedshort型变量,显然不符合对齐的规定。
    在x86上,类似的操作只会影响效率,但是在MIPS或者sparc上,可能就是一个error,因为它们要求必须字节对齐.

    七.如何查找与字节对齐方面的问题:

    如果出现对齐或者赋值问题首先查看
    1. 编译器的big little端设置
    2. 看这种体系本身是否支持非对齐访问
    3. 如果支持看设置了对齐与否,如果没有则看访问时需要加某些特殊的修饰来标志其特殊访问操作。

    八.相关文章:转自http://blog.csdn.net/goodluckyxl/archive/2005/10/17/506827.aspx

    ARM下的对齐处理 
    from DUI0067D_ADS1_2_CompLib

    3.13 type qulifiers

    有部分摘自ARM编译器文档对齐部分

    对齐的使用:
    1.__align(num)
       这个用于修改最高级别对象的字节边界。在汇编中使用LDRD或者STRD时
       就要用到此命令__align(8)进行修饰限制。来保证数据对象是相应对齐。
       这个修饰对象的命令最大是8个字节限制,可以让2字节的对象进行4字节
       对齐,但是不能让4字节的对象2字节对齐。
       __align是存储类修改,他只修饰最高级类型对象不能用于结构或者函数对象。
       
    2.__packed 
    __packed是进行一字节对齐
    1.不能对packed的对象进行对齐
    2.所有对象的读写访问都进行非对齐访问
    3.float及包含float的结构联合及未用__packed的对象将不能字节对齐
    4.__packed对局部整形变量无影响
    5.强制由unpacked对象向packed对象转化是未定义,整形指针可以合法定
    义为packed。
         __packed int* p; //__packed int 则没有意义
    6.对齐或非对齐读写访问带来问题
    __packed struct STRUCT_TEST
    {
    char a;
    int b;
    char c;
    } ;    //定义如下结构此时b的起始地址一定是不对齐的
             //在栈中访问b可能有问题,因为栈上数据肯定是对齐访问[from CL]
    //将下面变量定义成全局静态不在栈上 
    static char* p;
    static struct STRUCT_TEST a;
    void Main()
    {
    __packed int* q; //此时定义成__packed来修饰当前q指向为非对齐的数据地址下面的访问则可以

    p = (char*)&a;          
    q = (int*)(p+1);      

    *q = 0x87654321; 
    /*   
    得到赋值的汇编指令很清楚
    ldr      r5,0x20001590 ; = #0x12345678
    [0xe1a00005]   mov      r0,r5
    [0xeb0000b0]   bl       __rt_uwrite4 //在此处调用一个写4byte的操作函数 
          
    [0xe5c10000]   strb     r0,[r1,#0]   //函数进行4次strb操作然后返回保证了数据正确的访问
    [0xe1a02420]   mov      r2,r0,lsr #8
    [0xe5c12001]   strb     r2,[r1,#1]
    [0xe1a02820]   mov      r2,r0,lsr #16
    [0xe5c12002]   strb     r2,[r1,#2]
    [0xe1a02c20]   mov      r2,r0,lsr #24
    [0xe5c12003]   strb     r2,[r1,#3]
    [0xe1a0f00e]   mov      pc,r14
    */

    /*
    如果q没有加__packed修饰则汇编出来指令是这样直接会导致奇地址处访问失败
    [0xe59f2018]   ldr      r2,0x20001594 ; = #0x87654321
    [0xe5812000]   str      r2,[r1,#0]
    */

    //这样可以很清楚的看到非对齐访问是如何产生错误的
    //以及如何消除非对齐访问带来问题
    //也可以看到非对齐访问和对齐访问的指令差异导致效率问题
    }

    PS:读后
    1、明确结构的指定对齐值,如VC2005下是8。或者是由语句“#pragma pack (value)”指定的值。
    2、按照结构数据变量顺序相应计算。按照结构的指定对齐值进行占位计算。举例说明(默认对齐为8位):

    以下结构中,
    结构体或者类的自身对齐值(其成员中自身对齐值最大的那个值)为:
    double 长度为8
    指定对齐值为默认对齐值为8位。

    typedef struct
    {
       char x1;    //占据第1个8位的前1位,第1个8位剩下7位
       double x2;    //剩下的7位无法满足长度,本长度为8,开辟一个新的8位,第2个8位刚好用完
       size_t x3;    //开辟第3个8位,占据其中4位,剩余4位。
       unsigned short x4; //将第3个8位的后4位占据,第3个8位刚好用完
       int x5;     //开辟第4个8位,占据前4位
       double x6;    //开辟第5个8位,刚好用完
       char x7;    //开辟第6个8位,占据一位。其余为对齐占位,总计6*8=48位
    }x;

    以下结构中,
    结构体或者类的自身对齐值(其成员中自身对齐值最大的那个值)为:
    double 长度为8,因为指定为4,所以还是为4
    指定对齐值4位。

    #pragma pack (4)
    typedef struct
    {
       char y1;    //占据第1个4位的前1位,第一个4位剩下3位
       double y2;    //剩下的3位无法满足长度,本长度为8,开辟2个新的4位,刚好用完
       size_t y3;    //开辟第4个4位,占据其中4位,刚好用完。
       unsigned short y4; //开辟第5个4位,占用2位
       int y5;     //开辟第6个4位,刚好用完
       double y6;    //开辟第7、8个4位,刚好用完
       char y7;    //开辟第9个4位,占据1位。其余3位补齐。总计4*9=36位
    }y;
    #pragma pack ()



    from: http://blog.chinaunix.net/uid-14802518-id-2784907.html

    展开全文
  • C语言struct字节对齐总结

    千次阅读 2010-10-11 22:33:00
    最近不少同学开始找工作,很多关于C语言和C++的细节问题被重新揪出来称为热门话题...关于C语言里struct字节对齐的问题,网上查了一些结果,发现不是很全面(一般都没有关于struct里出现位字段时的总结),这里总结一下。

    最近不少同学开始找工作,很多关于C语言和C++的细节问题被重新揪出来称为热门话题。关于C语言里struct字节对齐的问题,网上查了一些结果,发现不是很全面(一般都没有关于struct里出现位字段时的总结),这里总结一下。

     

    字节对齐的原因:在特定的计算机系统平台下,提高内存访问的效率。在不同的编译器和不同的平台下,字节对齐规则不太一样。

     

    Win32平台下Visual C++ 6.0编译器中字节对齐的总结:

     

     

     

     

     

    展开全文
  • 【每日一C之三】struct字节对齐方式

    千次阅读 2014-03-28 19:14:55
    每日一C之struct字节对齐方式  每天拾一个C语言贝壳,厚积薄发,积跬步以致千里。  今日贝壳:结构体struct是多个相互关联数据的集合,这些数据以整体形式存储在内存。 struct A{ char a; //char占...
  • struct 字节对齐详解与大小端模式

    千次阅读 2015-04-02 14:17:57
    什么是字节对齐,为什么要对齐?  现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特定的内存地址访问,这就需要...
  • 什么是字节对齐,为什么要对齐? 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特 定的内存地址访问,这就需要...
  • 字节对齐问题在面试笔试中经常碰到,自己也在这里经常碰到坑,今天索性把这方面搞清楚,记录自己这方面的学习过程。大端小端法机器的大端小端问题一直是一个常考的点,并且struct的内存布局问题和这个大端小端有很大...
  • [转自:http://ieoqmdce.blog.163.com/blog/static/389399542009636836665/] 在编程中,我们常常会碰到字节对齐这方面的问题,偶就曾经碰到过。公司要求我把一段在Linux下的源代码改为运行在Windows下,偶修正了...
  • 字节对齐规则

    千次阅读 2015-08-19 11:30:26
    字节对齐这块知识点看了好几遍,总是忘,今天又碰到了,就在这整理一下。 64位与32位编译器操作系统的区别: 1 、64位与32位linux c开发时默认字节对齐方式分别为8和4字节。 2 、 32和64位C语言内置数据类型,如下...
  • C语言结构体字节对齐规则

    千次阅读 2019-04-12 10:55:40
    C语言结构体字节对齐规则 基本规则 规则1 :结构体(struct)的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存放在offset为该数据成员大小的整数倍的地方(比如int在32位机为4字节,则要从4的...
  • C 结构体字节对齐规则

    千次阅读 2018-01-29 11:10:32
    文档下载:结构体字节对齐规则 原则1:数据成员的对齐规则(以最大的类型字节为单位)。 结构体(struct)的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存放在offset为该数据成员大小的整数倍的...
  • 涉及struct字节对齐,代码中发现自己struct占用的字节数和自认为的有出入,故搜集相关资料,整理,仅作个人记录先介绍一下4个基本概念: 1.数据类型自身的对齐值:对于char型数据,其自身对齐值为1,对于short型...
  • C语言字节对齐规则总结

    千次阅读 2018-10-23 16:16:30
    原始链接源自 https://www.cnblogs.com/clover-toeic/p/3853132.html , 从上面博客中学习总结得到下面的文章。... 此外,是由于对内存的存取效率问题,如果存放的地址不对齐,取一个4字节的数据,可能会需...
  • 结构体字节对齐规则

    2014-08-20 22:36:30
    为了加快数据存取的速度,编译器默认情况下会对结构体成员和结构体本身存储位置进行处理,使其存放的起始地址是一定字节数的倍数,而不是顺序存放,称为字节对齐. (以下这3条规则摘自姜学锋,周果清,刘君瑞老师共编的...
  • struct字节对齐问题(通过pragma pack(n)改变字节对齐的例子) 佟强 2008.10.9 通过#pragma pack(n)改变C编译器的字节对齐方式,在C语言中,结构是一种复合数据类型,其构成元素既可以是基本数据类型(如int、...
  • 下面我们使用预编译指令#...#progma pack (2) /*指定按2字节对齐*/ struct C { char b; int a; short c; }; #progma pack () /*取消指定对齐,恢复缺省对齐*/ sizeof(struct C)值是8。 不字节对齐的...
  • 数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员大小(只要该成员有子成员,比如说是数组,结构体等...
  • Python: struct 模块之字节对齐问题

    千次阅读 2019-04-21 19:22:08
    PythonPythonPython 在二进制写文件时,可以用 structstructstruct 模块将数据捆绑成结构体转化成字节流,为了方便与 CCC 交互,避免 CCC 在读取二进制字节流时因为 CCC 的字节对齐问题而造成不必要的麻烦,...
  • 结构体4字节对齐规则的详解

    千次阅读 2013-04-17 17:08:57
    C++中结构体变量的存储为什么有个4字节对齐规则,这里是假设32位机器上,CPU在读取内存数据的时候4字节对齐会取得更快的速度;这是因为:1字节8位,4字节正好32位,而32位机器的寄存器,地址什么的都是32位的,正好...
  • struct结构体字节对齐原则及为什么要对齐?

    万次阅读 多人点赞 2019-01-06 11:30:21
    http://blog.sina.com.cn/s/blog_14ecf1a5b0102x27j.html ... //-------------------------------------------------------- 本文目录结构 |-为什么结构体内存对齐 |-结构体内...

空空如也

空空如也

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

struct字节对齐规则