精华内容
下载资源
问答
  • (转)C语言 - 结构体所占字节数  在用sizeof运算符求算某结构体所占空间时,并不是简单地将结构体中所有元素各自占的空间相加,这里涉及到内存字节对齐的问题。从理论上讲,对于任何变量的访问都可以从任何地址...

    (转)C语言 - 结构体所占字节数

           在用sizeof运算符求算某结构体所占空间时,并不是简单地将结构体中所有元素各自占的空间相加,这里涉及到内存字节对齐的问题。从理论上讲,对于任何变量的访问都可以从任何地址开始访问,但是事实上不是如此,实际上访问特定类型的变量只能在特定的地址访问,这就需要各个变量在空间上按一定的规则排列,而不是简单地顺序排列,这就是内存对齐。

          内存对齐的原因:

          1)某些平台只能在特定的地址处访问特定类型的数据;

          2)提高存取数据的速度。比如有的平台每次都是从偶地址处读取数据,对于一个int型的变量,若从偶地址单元处存放,则只需一个读取周期即可读取该变量;但是若从奇地址单元处存放,则需要2个读取周期读取该变量。

      在C99标准中,对于内存对齐的细节没有作过多的描述,具体的实现交由编译器去处理,所以在不同的编译环境下,内存对齐可能略有不同,但是对齐的最基本原则是一致的,对于结构体的字节对齐主要有下面两点:

          1)结构体每个成员相对结构体首地址的偏移量(offset)是对齐参数的整数倍,如有需要会在成员之间填充字节。编译器在为结构体成员开辟空间时,首先检查预开辟空间的地址相对于结构体首地址的偏移量是否为对齐参数的整数倍,若是,则存放该成员;若不是,则填充若干字节,以达到整数倍的要求。

          2)结构体变量所占空间的大小是对齐参数大小的整数倍。如有需要会在最后一个成员末尾填充若干字节使得所占空间大小是对齐参数大小的整数倍。

       注意:在看这两条原则之前,先了解一下对齐参数这个概念。对于每个变量,它自身有对齐参数,这个自身对齐参数在不同编译环境下不同。下面列举的是两种最常见的编译环境下各种类型变量的自身对齐参数


      从上面可以发现,在windows(32)/VC6.0下各种类型的变量的自身对齐参数就是该类型变量所占字节数的大小,而在linux(32)/GCCdouble类型的变量自身对齐参数是4,是因为linux(32)/GCC下如果该类型变量的长度没有超过CPU的字长,则以该类型变量的长度作为自身对齐参数,如果该类型变量的长度超过CPU字长,则自身对齐参数为CPU字长,而32位系统其CPU字长是4,所以linux(32)/GCC下double类型的变量自身对齐参数是4,如果是在Linux(64)下,则double类型的自身对齐参数是8。

      除了变量的自身对齐参数外,还有一个对齐参数,就是每个编译器默认的对齐参数#pragmapack(n),这个值可以通过代码去设定,如果没有设定,则取系统的默认值。在windows(32)/VC6.0下,n的取值可以为1、2、4、8,默认情况下为8。在linux(32)/GCC下,n的取值只能为1、2、4,默认情况下为4。注意像DEV-CPP、MinGW等在windows下n的取值和VC的相同。

      了解了这2个概念之后,可以理解上面2条原则了。对于第一条原则,每个变量相对于结构体的首地址的偏移量必须是对齐参数的整数倍,这句话中的对齐参数是取每个变量自身对齐参数和系统默认对齐参数#pragma pack(n)较小的一个。举个简单的例子,比如在结构体A中有变量int a,a的自身对齐参数为4(环境为windows/vc),而VC默认的对齐参数为8,取较小者,则对于a,它相对于结构体A的起始地址的偏移量必须是4的倍数。

      对于第二条原则,结构体变量所占空间的大小是对齐参数的整数倍。这句话中的对齐参数有点复杂,它是取结构体中所有变量的对齐参数的最大值和系统默认对齐参数#pragma pack(n)比较,较小者作为对齐参数。举个例子假如在结构体A中先后定义了两个变量int a;double b;对于变量a,它的自身对齐参数为4,而#pragma pack(n)值默认为8,则a的对齐参数为4;b的自身对齐参数为8,而#pragma pack(n)的默认值为8,则b的对齐参数为8。即结构体内的每个遍历也要取自身的对齐参数和默认对齐参数比较,取较小者作为这个变量的对齐参数。由于a的最终对齐参数为4,b的最终对齐参数为8,那么两者较大者是8,然后再拿8和#pragma pack(n)作比较,取较小者作为对齐参数,也就是8,即意味着结构体最终的大小必须能被8整除。

    下面是测试例子:

    注意:以下例子的测试结果均在windows(32)/VC下测试的,其默认对齐参数为8 

    [cpp] view plain copy
    1. #include <iostream>  
    2. using namespace std;  
    3. //#pragma pack(4)    //设置4字节对齐   
    4. //#pragma pack()     //取消4字节对齐   
    5.   
    6. typedef struct node1  
    7. {  
    8.     int a;  
    9.     char b;  
    10.     short c;  
    11. }S1;  
    12.   
    13. typedef struct node2  
    14. {  
    15.     char a;  
    16.     int b;  
    17.     short c;  
    18. }S2;  
    19.   
    20. typedef struct node3  
    21. {  
    22.     int a;  
    23.     short b;  
    24.     static int c;  
    25. }S3;  
    26.   
    27. typedef struct node4  
    28. {  
    29.     bool a;  
    30.     S1 s1;  
    31.     short b;  
    32. }S4;  
    33.   
    34. typedef struct node5  
    35. {  
    36.     bool a;  
    37.     S1 s1;  
    38.     double b;  
    39.     int c;  
    40. }S5;  
    41.   
    42.   
    43.   
    44. int main(int argc, char *argv[])  
    45. {  
    46.     cout<<sizeof(char)<<" "<<sizeof(short)<<" "<<sizeof(int)<<" "<<sizeof(float)<<" "<<sizeof(double)<<endl;  
    47.     S1 s1;  
    48.     S2 s2;  
    49.     S3 s3;  
    50.     S4 s4;  
    51.     S5 s5;  
    52.     cout<<sizeof(s1)<<" "<<sizeof(s2)<<" "<<sizeof(s3)<<" "<<sizeof(s4)<<" "<<sizeof(s5)<<endl;  
    53.     return 0;  
    54. }  

    输出结果:

    [cpp] view plain copy
    1. 1 2 4 4 8  
    2. 8 12 8 16 32  

    下面解释一下其中的几个结构体字节分配的情况

    比如对于node2

    [cpp] view plain copy
    1. typedef struct node2  
    2. {  
    3.     chara;  
    4.     intb;  
    5.     shortc;  
    6. }S2;  

    sizeof(S2)=12;

    对于变量a,它的自身对齐参数为1,#pragma pack(n)默认值为8,则最终a的对齐参数为1,为其分配1字节的空间,它相对于结构体起始地址的偏移量为0,能被1整除;

      对于变量b,它的自身对齐参数为4,#pragma pack(n)默认值为8,则最终b的对齐参数为4,接下来的地址相对于结构体的起始地址的偏移量为1,1不能够整除4,所以需要在a后面填充3字节使得偏移量达到4,然后再为b分配4字节的空间

      对于变量c,它的自身对齐参数为2,#pragma pack(n)默认值为8,则最终c的对齐参数为2,而接下来的地址相对于结构体的起始地址的偏移量为8,能整除2,所以直接为c分配2字节的空间。

      此时结构体所占的字节数为1+3+4+2=10字节

      最后由于a,b,c的最终对齐参数分别为1,4,2,最大为4,#pragmapack(n)的默认值为8,则结构体变量最后的大小必须能被4整除。而10不能够整除4,所以需要在后面填充2字节达到12字节。其存储如下:

    [cpp] view plain copy
    1. |char|----|----|----|  4字节  
    2.  |--------int--------|  4字节  
    3.  |--short--|----|----|  4字节  

      总共占12个字节

    对于node3,含有静态数据成员 

    [cpp] view plain copy
    1. typedef struct node3  
    2. {  
    3.     int a;  
    4.     short b;  
    5.     static int c;  
    6. }S3;  

     

      则sizeof(S3)=8.这里结构体中包含静态数据成员,而静态数据成员的存放位置与结构体实例的存储地址无关(注意只有在C++中结构体中才能含有静态数据成员,而C中结构体中是不允许含有静态数据成员的)。其在内存中存储方式如下:

    [cpp] view plain copy
    1. |--------int--------|   4字节  
    2. |--short-|----|----|    4字节  

      而变量c是单独存放在静态数据区的,因此用siezof计算其大小时没有将c所占的空间计算进来。

    而对于node5,里面含有结构体变量

    [cpp] view plain copy
    1. typedef struct node5  
    2. {  
    3.     bool a;  
    4.     S1 s1;  
    5.     double b;  
    6.     int c;  
    7. }S5;  
    8.    

    sizeof(S5)=32。

      对于变量a,其自身对齐参数为1,#pragma pack(n)为8,则a的最终对齐参数为1,为它分配1字节的空间,它相对于结构体起始地址的偏移量为0,能被1整除;

      对于s1,它的自身对齐参数为4(对于结构体变量,它的自身对齐参数为它里面各个变量最终对齐参数的最大值),#pragma pack(n)为8,所以s1的最终对齐参数为4,接下来的地址相对于结构体起始地址的偏移量为1,不能被4整除,所以需要在a后面填充3字节达到4,为其分配8字节的空间;

      对于变量b,它的自身对齐参数为8,#pragma pack(n)的默认值为8,则b的最终对齐参数为8,接下来的地址相对于结构体起始地址的偏移量为12,不能被8整除,所以需要在s1后面填充4字节达到16,再为b分配8字节的空间;

      对于变量c,它的自身对齐参数为4,#pragma pack(n)的默认值为8,则c的最终对齐参数为4,接下来相对于结构体其实地址的偏移量为24,能够被4整除,所以直接为c分配4字节的空间。

      此时结构体所占字节数为1+3+8+4+8+4=28字节。

      对于整个结构体来说,各个变量的最终对齐参数为1484,最大值为8#pragma pack(n)默认值为8,所以最终结构体的大小必须是8的倍数,因此需要在最后面填充4字节达到32字节。其存储如下:

    [cpp] view plain copy
    1. |--------bool--------|   4字节  
    2. |---------s1---------|   8字节  
    3. |--------------------|    4字节  
    4. |--------double------|   8字节  
    5. |----int----|---------|    8字节   


      另外可以显示地在程序中使用#pragma pack(n)来设置系统默认的对齐参数,在显示设置之后,则以设置的值作为标准,其它的和上面所讲的类似,就不再赘述了,读者可以自行上机试验一下。如果需要取消设置,可以用#pragma pack()来取消。

    当把系统默认对齐参数设置为4时,即#pragma pack(n)

    输出结果是:

    [cpp] view plain copy
    1. 1 2 4 4 8  
    2. 8 12 8 16 24   

    共用体类型:
    typedef union 
    {
    long i; 
    int k[5]; 
    char c;
    } DATE;
    struct data 
    {
     int cat; DATE cow; double dog;
    } too;
    则语句printf("%d",sizeof(DATE)+sizeof(struct data)); 
    执行结果是:_____
    【标准答案】DATE是一个union, 变量公用空间.  里面最
    大的变量类型是int[5],  占用20个字节.  所以它的大小是
    20
    data 是一个struct,  每个变量分开占用空间.  依次为int4 + 
    DATE20 + double8 = 32.
    所以结果是20 + 32 = 52.
    展开全文
  • C语言 - 结构体所占字节数

    千次阅读 2018-07-04 11:57:35
    在用sizeof运算符求算某结构体所占空间时,并不是简单地将结构体中所有元素各自占的空间相加,这里涉及到内存字节对齐的问题。从理论上讲,对于任何变量的访问都可以从任何地址开始访问,但是事实上不是如此,实际...

    核心:
    1.每个元素的首地址偏移量必须能整除该元素的长度。
    2. 整个结构体的长度必须能整除最长元素的字节数。

    下文转自:https://blog.csdn.net/u012243115/article/details/44563331,仅作笔记之用。

    在用sizeof运算符求算某结构体所占空间时,并不是简单地将结构体中所有元素各自占的空间相加,这里涉及到内存字节对齐的问题。从理论上讲,对于任何变量的访问都可以从任何地址开始访问,但是事实上不是如此,实际上访问特定类型的变量只能在特定的地址访问,这就需要各个变量在空间上按一定的规则排列,而不是简单地顺序排列,这就是内存对齐。

    内存对齐的原因:

    1)某些平台只能在特定的地址处访问特定类型的数据;

    2)提高存取数据的速度。比如有的平台每次都是从偶地址处读取数据,对于一个int型的变量,若从偶地址单元处存放,则只需一个读取周期即可读取该变量;但是若从奇地址单元处存放,则需要2个读取周期读取该变量。

      在C99标准中,对于内存对齐的细节没有作过多的描述,具体的实现交由编译器去处理,所以在不同的编译环境下,内存对齐可能略有不同,但是对齐的最基本原则是一致的,对于结构体的字节对齐主要有下面两点:

    1)结构体每个成员相对结构体首地址的偏移量(offset)是对齐参数的整数倍,如有需要会在成员之间填充字节。编译器在为结构体成员开辟空间时,首先检查预开辟空间的地址相对于结构体首地址的偏移量是否为对齐参数的整数倍,若是,则存放该成员;若不是,则填充若干字节,以达到整数倍的要求。

    2)结构体变量所占空间的大小是对齐参数大小的整数倍。如有需要会在最后一个成员末尾填充若干字节使得所占空间大小是对齐参数大小的整数倍。

      注意:在看这两条原则之前,先了解一下对齐参数这个概念。对于每个变量,它自身有对齐参数,这个自身对齐参数在不同编译环境下不同。下面列举的是两种最常见的编译环境下各种类型变量的自身对齐参数


      从上面可以发现,在windows(32)/VC6.0下各种类型的变量的自身对齐参数就是该类型变量所占字节数的大小,而在linux(32)/GCCdouble类型的变量自身对齐参数是4,是因为linux(32)/GCC下如果该类型变量的长度没有超过CPU的字长,则以该类型变量的长度作为自身对齐参数,如果该类型变量的长度超过CPU字长,则自身对齐参数为CPU字长,而32位系统其CPU字长是4,所以linux(32)/GCC下double类型的变量自身对齐参数是4,如果是在Linux(64)下,则double类型的自身对齐参数是8。

      除了变量的自身对齐参数外,还有一个对齐参数,就是每个编译器默认的对齐参数#pragmapack(n),这个值可以通过代码去设定,如果没有设定,则取系统的默认值。在windows(32)/VC6.0下,n的取值可以为1、2、4、8,默认情况下为8。在linux(32)/GCC下,n的取值只能为1、2、4,默认情况下为4。注意像DEV-CPP、MinGW等在windows下n的取值和VC的相同。

      了解了这2个概念之后,可以理解上面2条原则了。对于第一条原则,每个变量相对于结构体的首地址的偏移量必须是对齐参数的整数倍,这句话中的对齐参数是取每个变量自身对齐参数和系统默认对齐参数#pragma pack(n)较小的一个。举个简单的例子,比如在结构体A中有变量int a,a的自身对齐参数为4(环境为windows/vc),而VC默认的对齐参数为8,取较小者,则对于a,它相对于结构体A的起始地址的偏移量必须是4的倍数。

      对于第二条原则,结构体变量所占空间的大小是对齐参数的整数倍。这句话中的对齐参数有点复杂,它是取结构体中所有变量的对齐参数的最大值和系统默认对齐参数#pragma pack(n)比较,较小者作为对齐参数。举个例子假如在结构体A中先后定义了两个变量int a;double b;对于变量a,它的自身对齐参数为4,而#pragma pack(n)值默认为8,则a的对齐参数为4;b的自身对齐参数为8,而#pragma pack(n)的默认值为8,则b的对齐参数为8。即结构体内的每个遍历也要取自身的对齐参数和默认对齐参数比较,取较小者作为这个变量的对齐参数。由于a的最终对齐参数为4,b的最终对齐参数为8,那么两者较大者是8,然后再拿8和#pragma pack(n)作比较,取较小者作为对齐参数,也就是8,即意味着结构体最终的大小必须能被8整除。

    下面是测试例子:

    注意:以下例子的测试结果均在windows(32)/VC下测试的,其默认对齐参数为8

    #include <iostream>
    using namespace std;
    //#pragma pack(4)    //设置4字节对齐 
    //#pragma pack()     //取消4字节对齐 
    
    typedef struct node1
    {
        int a;
        char b;
        short c;
    }S1;
    
    typedef struct node2
    {
        char a;
        int b;
        short c;
    }S2;
    
    typedef struct node3
    {
        int a;
        short b;
        static int c;
    }S3;
    
    typedef struct node4
    {
        bool a;
        S1 s1;
        short b;
    }S4;
    
    typedef struct node5
    {
        bool a;
        S1 s1;
        double b;
        int c;
    }S5;
    
    
    
    int main(int argc, char *argv[])
    {
        cout<<sizeof(char)<<" "<<sizeof(short)<<" "<<sizeof(int)<<" "<<sizeof(float)<<" "<<sizeof(double)<<endl;
        S1 s1;
        S2 s2;
        S3 s3;
        S4 s4;
        S5 s5;
        cout<<sizeof(s1)<<" "<<sizeof(s2)<<" "<<sizeof(s3)<<" "<<sizeof(s4)<<" "<<sizeof(s5)<<endl;
        return 0;
    }

    输出结果:

    1 2 4 4 8
    8 12 8 16 32

    下面解释一下其中的几个结构体字节分配的情况

    比如对于node2

    typedef struct node2
    {
        chara;
        intb;
        shortc;
    }S2;
    

    sizeof(S2)=12;

    对于变量a,它的自身对齐参数为1,#pragma pack(n)默认值为8,则最终a的对齐参数为1,为其分配1字节的空间,它相对于结构体起始地址的偏移量为0,能被4整除;

      对于变量b,它的自身对齐参数为4,#pragma pack(n)默认值为8,则最终b的对齐参数为4,接下来的地址相对于结构体的起始地址的偏移量为1,1不能够整除4,所以需要在a后面填充3字节使得偏移量达到4,然后再为b分配4字节的空间;

      对于变量c,它的自身对齐参数为2,#pragma pack(n)默认值为8,则最终c的对齐参数为2,而接下来的地址相对于结构体的起始地址的偏移量为8,能整除2,所以直接为c分配2字节的空间。

      此时结构体所占的字节数为1+3+4+2=10字节

      最后由于a,b,c的最终对齐参数分别为1,4,2,最大为4,#pragmapack(n)的默认值为8,则结构体变量最后的大小必须能被4整除。而10不能够整除4,所以需要在后面填充2字节达到12字节。其存储如下:

      |char|----|----|----|  4字节
       |--------int--------|  4字节
       |--short--|----|----|  4字节

      总共占12个字节

    对于node3,含有静态数据成员

    typedef struct node3
    {
        int a;
        short b;
        static int c;
    }S3;

      则sizeof(S3)=8.这里结构体中包含静态数据成员,而静态数据成员的存放位置与结构体实例的存储地址无关(注意只有在C++中结构体中才能含有静态数据成员,而C中结构体中是不允许含有静态数据成员的)。其在内存中存储方式如下:

      |--------int--------|   4字节
      |--short-|----|----|    4字节

      而变量c是单独存放在静态数据区的,因此用siezof计算其大小时没有将c所占的空间计算进来。

    而对于node5,里面含有结构体变量

    typedef struct node5
    {
        bool a;
        S1 s1;
        double b;
        int c;
    }S5;
    
    

    sizeof(S5)=32。

      对于变量a,其自身对齐参数为1,#pragma pack(n)为8,则a的最终对齐参数为1,为它分配1字节的空间,它相对于结构体起始地址的偏移量为0,能被1整除;

      对于s1,它的自身对齐参数为4(对于结构体变量,它的自身对齐参数为它里面各个变量最终对齐参数的最大值),#pragma pack(n)为8,所以s1的最终对齐参数为4,接下来的地址相对于结构体起始地址的偏移量为1,不能被4整除,所以需要在a后面填充3字节达到4,为其分配8字节的空间;

      对于变量b,它的自身对齐参数为8,#pragma pack(n)的默认值为8,则b的最终对齐参数为8,接下来的地址相对于结构体起始地址的偏移量为12,不能被8整除,所以需要在s1后面填充4字节达到16,再为b分配8字节的空间;

      对于变量c,它的自身对齐参数为4,#pragma pack(n)的默认值为8,则c的最终对齐参数为4,接下来相对于结构体其实地址的偏移量为24,能够被4整除,所以直接为c分配4字节的空间。

      此时结构体所占字节数为1+3+8+4+8+4=28字节。

      对于整个结构体来说,各个变量的最终对齐参数为1484,最大值为8#pragma pack(n)默认值为8,所以最终结构体的大小必须是8的倍数,因此需要在最后面填充4字节达到32字节。其存储如下:

       |--------bool--------|   4字节
       |---------s1---------|   8字节
       |--------------------|    4字节
       |--------double------|   8字节
       |----int----|---------|    8字节 


      另外可以显示地在程序中使用#pragma pack(n)来设置系统默认的对齐参数,在显示设置之后,则以设置的值作为标准,其它的和上面所讲的类似,就不再赘述了,读者可以自行上机试验一下。如果需要取消设置,可以用#pragma pack()来取消。

    当把系统默认对齐参数设置为4时,即#pragma pack(n)

    输出结果是:

    1 2 4 4 8
    8 12 8 16 24 


    展开全文
  • c语言各类型所占字节数

    万次阅读 2018-07-25 12:18:36
    (1)struct结构体变量大小等于结构体中的各个成员变量所占内存大小总和,union共用体变量大小等于共用体结构中占用内存最大的成员的内存大小;联合体中占用内存空间最大的字段加上填充字节(对齐字节后所需字节数)...

    (1)struct结构体变量大小等于结构体中的各个成员变量所占内存大小总和,union共用体变量大小等于共用体结构中占用内存最大的成员的内存大小; 联合体中占用内存空间最大的字段加上填充字节(对齐字节后所需字节数)。

    (2)枚举类型,指一个被命名的整型常数的集合。即枚举类型,本质上是一组常数的集合体,只是这些常数有各自的命名。枚举类型,是一种用户自定义数据类型。

    枚举变量,由枚举类型定义的变量。枚举变量的大小,即枚举类型所占内存的大小。由于枚举变量的赋值,一次只能存放枚举结构中的某个常数。所以枚举变量的大小,实质是常数所占内存空间的大小(常数为int类型,当前主流的编译器中一般是32位机器和64位机器中int型都是4个字节),枚举类型所占内存大小也是这样。

    (3)指针其实就是地址, 与它所指的基类型无关, 更与C语言无关, 只与机器有关. 如果你的机器是16位寻址的, 那指针就是16位的,2个字节, 如果是32位寻址的, 指针也是32位的,4个字节.如果寻址是64位的,指针也是64位,8个字节。

    (4)

    类型 16位 32 位 64位
    char 1 1 1
    short int 2 2 2
    int 2 4 4
    unsigned int 2 4 4
    float 4 4 4
    double 8 8 8
    long 4 4 8
    long long 8 8 8
    unsigned long 4 4 8

    首先来看字符类型,这里单指char , char变量在内存中存储的是字符对应的ASCII码值。所以长度也是固定的,不管在哪种编译器下,均为1个字节。

    再来看 浮点类型,C中的浮点类型有俩种,float和double,与整数不同的是,浮点数的长度适中的固定的,float占用4个字节,double占用8个字节。

    最后来看 整型类型,查阅资料后发现虽然16位、32位或者64位的机子各种类型并不一样,但有几条规则(ANSI/ ISO制定):

    • short 至少占用2个字节
    • int 建议为一个机器字长,32位环境下为4字节,64位环境下为8字节
    • short 的长度不能大于int, long 的长度不能小于int

    sizeof(a)=?
    解析:

    首先,#pragma pack(2)   强制设定为2字节对

    i   4字节

    u  一个为13,一个为4,默认为4字节对齐;

         union占对齐后数据的最大字节大小,默认为13+3=4*4=16;

         但是,该处强制为2字节对齐,实际为13+1=2*7=14字节

    color   枚举类型的实例  4字节

    4+14+4=22字节

    展开全文
  • C语言结构体字节对齐

    2021-02-08 14:34:16
    理论上所有成员在分配内存时都是紧接在前一个变量后面依次填充的,但是如果是“以 N 对齐”为原则,那么,如果一行中剩下的空间不足以填充某成员变量,即剩下的空间小于某成员变量的数据类型所占字节数,...

    前言

    对C语言结构体进行字节对齐的合理排列并不仅仅可以节省非常大的空间,最重要的是体现个人编程的良好习惯。

    以N对齐方式

    所谓的以N对齐方式纯属我瞎掰的,哈哈。

    所有的结构体成员在定义结构体分配内存时都要与所有成员中占内存最多的数据类型所占内存空间的字节数对齐

    **假如这个字节数为 N,**那么对齐的原则是:理论上所有成员在分配内存时都是紧接在前一个变量后面依次填充的,但是如果是“以 N 对齐”为原则,那么,如果一行中剩下的空间不足以填充某成员变量,即剩下的空间小于某成员变量的数据类型所占的字节数,则该成员变量在分配内存时另起一行分配。
    假设一个结构体按照如下方式进行排列:

    typedef struct TAutoTestParseTag TAutoTestParse;
    struct TAutoTestParseTag
    {
        int a;
        short b;
        char c; 
    };
    

    此时在结构体成员中,占内存最多的是成员a,所以该结构体是以4字节进行对齐的。

    因为成员a、b、c理论上是紧邻相接的,且成员a占四个字节最大,后面分配的b占两个字节,紧跟着的c占一个字节,所以这里实际有效的字节数是4+2+1等于7个字节。

    但由于对齐,所以最后总字节数是8,由于b和c一共占3个字节,但是此时结构体是按照4字节对齐的,所以字成员c的后面填充了一个空的字节。

    如果更换下排列方式:

    typedef struct TAutoTestParseTag TAutoTestParse;
    struct TAutoTestParseTag
    {
        short b;
         int a;
        char c; 
    };
    

    此时有效字节数为1+4+2等于7.

    由于字节对齐,在b的后面还空有两个字节,但是不足以存放成员a,所以填充两个空字节,在存放成员a。

    在c后面会进行填充3个空字节,所以最后的结构体所占字节数为2+2+4+1+3等于12.

    可以发现不同的排列对最后结构体的所占空间影响还是蛮大的。

    可能现在的一些机器已经有很大的空间来让我们用来浪费了,但是从程序员的自我修养角度来说还是尽量节省空间吧。但是!!!永远不要因为要节省空间,来让结构体内部成员的排列看起来影响代码的阅读性!!!,否则维护时可能会付出很大的代价。

    展开全文
  • (1)struct结构体变量大小等于结构体中的各个成员变量所占内存大小总和,union共用体变量大小等于共用体结构中占用内存最大的成员的内存大小; 联合体中占用内存空间最大的字段加上...
  • C语言结构体数组+结构体类型指针+指向结构体数组的指针+typedef类型结构体数组两种结构体数组的定义形式用sizeof运算符求结构体数组所占字节数结构体类型指针指向结构体数组的指针typedef类型 结构体数组 如果要处理...
  • 结构体定义时,我们可以指定某个成员变量所占用的二进制位数(Bit),这就是位域。 structtest{ unsigned m; unsigned n:4; unsignedchar ch:6; } :后面的数字用来限定成员变量占用的位数。成员 m 没有限制...
  • C语言结构体大小计算

    2020-10-27 09:19:00
    即,最后一个成员的偏移量加上最后一个成员的大小再加上末尾的填充字节数。 结构体内偏移规则 1、每个成员的偏移量都必须是当前成员所占内存大小的整数倍如果不是编译器会在成员之间加上填充字节。 2、当所有成员...
  • 结构体其所占的字节数是所占字节数之和 结构体类型的定义 struct 结构体名 { //类型说明符 成员名;叫做成员变量 成员列表 };//分号不能丢 结构体变量的定义 方法一:先结构体类型的定义,后结构体变量的说明.
  • 在学习C语言的时候很多人可能遇到了和我同样的问题,就是无法正确计算出C语言结构体所占字节的总的大小。首先,在开始计算结构体占用字节大小之前,我们要先搞懂什么是结构体的对齐和补齐。为什么会有结构体的对齐与...
  • 1 1变量 a 所占的内存字节数是 o 假设整型 int 为 4 字节 struct stu { char name[20]; long int n; int score[4]; } a ; 28 B) 30 C) 32 D) 46 C 2下列程序的输出结果是 A)5 B)6 C)7 D)8 struct abc {int a,b,c;}; ...
  • 1 1变量 a 所占的 内存 字节数是 假设整型 int 为 4 字 节 structstu {charname[20]; longintn; intscore[4]; }a; 28B)30 C)32D)46 C 2下列程序的输出结果是 A)5B)6 C)7D)8 structabc {inta,b,c;}; main) {...
  • 共用体(union)所占字节数是最大的成员内存。 结构体(struct)类型占用的内存空间的计算方法: 首先需要确定是在32位系统,还算在64位系统  是所有成员的内存的和,但是需要注意,默认情况下是按照32位4字节...
  • C语言结构体对齐步骤: 结构体各成员对齐. 结构体总体对齐 C语言结构体对齐规则: 结构体(struct)的数据成员,第一个数据成员存放的地址为结构体变量偏移量为0的地址处. 其他结构体成员自身对齐时,存放的地址为min{...
  • 结构体所占的总字节数即sizeof()函数返回的值必须是最大成员的长度的整数倍,否则要进行“末尾填充”; c.若结构体A将结构体B作为其成员,则结构体B存储的首地址的偏移量必须为B中所含成员数据长度最大值的整数倍...
  • 对于共同体来说,其在内存中所占字节数为共同体中长度最大的元素所占用的字节数。 对于结构体来说,必须遵循结构体对齐的原则。 对齐原则:一般来说,结构体的对齐规则是先按数据类型自身进行对齐,然后再按整个...
  • 结构体变量后边带的冒号:

    千次阅读 2014-06-18 14:42:38
    C语言允许在一个结构体中以位为单位来指定其成员所占内存长度,这种以位为单位的成员成为“位段”或位域,利用位段能够用较少的位数存储数据。如: struct packed_data (该例子假定int占2个字节,因为在c语言中...
  • C语言复习_结构体

    2021-01-28 09:57:47
    结构体变量占字节数是各成员占字节数总和 结构体类型中成员定义与普通变量定义的区别 成员定义:不分配内存 变量定义:分配内存 共用体与结构体的区别 (1)关键字不同 (2)所占内存空间的区别:共用体各个成员...
  • 1、结构体变量的首地址,必须是结构体变量中的“最大基本数据类型成员所占字节数”的整数倍。(对齐) 2、结构体变量中的每个成员相对于结构体首地址的偏移量,都是该成员基本数据类型所占字节的整数倍。(对齐) 3...
  • C语言 字节对齐

    2018-11-03 22:46:38
    你是否有观察过结构体中数据变量所占字节数,以及结构体所占的字节数? 如:   图1 图2 图三 你是否知道图1,2,3中结构体所占的字节数么? 在此之前,我们需...
  • C语言定义变量后加冒号

    千次阅读 2017-10-31 10:05:58
    含义为,在结构体name汇总,成员变量var_name占用空间为n位。n为正整数,其值必须小于type类型占用的位数。比如type如果是int,4字节32位,那么n必须是1~31之间的整数。对于位域类型的成员,在赋值时如果实际值...
  • (1)、整体空间是占用空间最大的成员(的类型)所占字节数的整数倍; (2)、数据对齐原则---内存按结构体成员的先后顺序排列,当排到该成员时,其前面已摆放的空间大小必须是该成员类型大小的整数倍,如果不够则...
  • 结构体的大小,就是结构体在内存中占用的字节数。通俗来讲就是直接把 就是结构体中所有的变量(成员变量)占用的字节加起来。 实际使用中,为了更方便计算机对结构体变量寻址和取值,就要按一定规则 对变量...
  • 1、什么是结构体的内存对齐?...它不是简单的将成员变量类型所占字节数相加得7,而是根据成员变量中最大数据类型的宽度int来分配内存,分配三个int宽度的内存,三个成员变量各占4个字 节的内存,所以是3*4=12
  • C语言共用体和与结构体的区别

    千次阅读 2016-12-21 22:58:23
    共用体与结构体的区别共用体: 使用union 关键字 共用体内存长度是内部最长的数据类型的长度。 共用体的地址和内部各成员变量...结构体字节对齐:每个成员相对于结构体首地址的偏移量都得是当前成员所占内存大小的整
  • 摘要:sizeof是C语言中保留关键字,也可以认为是一种运算符,单目运算符。用于计算对象所占的字节数,通常用来查看变量、数组或结构体所占字节个数的操作运算符。
  • C++结构体,联合体

    2020-10-10 16:33:46
    C++结构体可以有函数成员,而C语言中的结构体不可以有函数成员,而只能有数据成员。...C++联合体中的所有数据成员公用一块内存单元,占的字节数为成员中占字节数最多的那个变量所占的字节数。 ...
  • c语言中sizeof()的特点及用法

    千次阅读 2017-09-22 19:38:51
    定义:sizeof是计算对象所占的字节数,通常用来查看变量、数组或结构体所占字节个数的操作运算符。  形式:sizeof()有三种语法形式: 1)用于数据类型:sizeof(type_name);//sizeof(类型); 2)用于变量...

空空如也

空空如也

1 2 3
收藏数 51
精华内容 20
关键字:

c语言结构体变量所占字节数

c语言 订阅