zoukankan      html  css  js  c++  java
  • 联合体union的详解

    1.概述

    联合体union的定义方式与结构体一样,但是二者有根本区别。

    在结构中各成员有各自的内存空间,一个结构变量的总长度是各成员长度之和。而在“联合”中,各成员共享一段内存空间,一个联合变量的长度等于各成员中最长的长度。

    2.联合体长度

    在The C Programming Language里面讲述union内存分配的原话是

    1)联合体就是一个结构

    2)联合体的所有成员相对于基地址的偏移量为0

    3)此结构空间要大到总够容纳最“宽”的成员

    4)并且,其对齐方式要适合于联合体中所有类型的成员

    我的理解可以概括为两点:

    1)联合体的结构空间要足够大,要等于最长的一个结构变量的空间,但是这个最长的空间要满足以下条件:

         1.要大于等于最长的一个结构变量的空间

          2.并且要能够整除其他结构变量的数据长度,即联合体空间对其他成员的元类型要能够整除(int a[5],其元类型为int,元类型长度为4),实际上就是要取一个元类型的最小公倍数。

    这儿举例来说

    union     
    {   
        float   fuel_load;   
        char a[5];  
        int   pallets;   
    }fighter; 


    这个结构体中,各个结构变量的空间分别为float   fuel_load; 占4个字节,char a[5];占5个字节,int pallets;占4个字节。通过“3)此结构空间要大到总够容纳最“宽”的成员”这句话,我们可以认为是结构体的空间为5个字节即可,但是“其对齐方式要适合于联合体中所有类型的成员”没有满足,对于这个问题,通过上面红色字体部分可以解决。,因此联合体空间为8.8可以整除 4(float、int长度)和1(char的长度),并且8大于数组5.

    再举一个例子有助于大家理解。

    struct   aircraft 
    { 
    int   wingspan; 
    int   passengers; 
    union   
    { 
    float   fuel_load; 
    float   bomb_load; 
    int   pallets; 
    }; 
    }fighter; 

    sizeof(fighter) 是12 。int   wingspan; int   passengers;两个int型 8个字节。union中 3个都是4个字节,因此union长度为4个字节。 

    3.内存分配

    一句话:联合体变量的各个成员都是从低字节开始公用的。即:所有的成员都是从低字节开始的。

    我们先为整个union分配一个空间,这个空间大小就是上面(2)内存分配中所讲述的。

    union {
          int i;
          char x[2];
    }a;
    int main(void)
    {
       a.x[0] = 10;
       a.x[1] = 1;
       printf("%d
    ",a.i);
       return 0;
    }

    其内存如下图所示。a.x[0] 处于低字节,x[1]高字节。当调用i这个成员变量的时候,其开始地址仍然是从起始地址开始,数4个字节输出。因此为 256 + 10 = 266

    (改低地址处:0000 1010)

    程序附上:

    #include <string.h>
    #include <stdio.h>
    #include <unistd.h>
    #if 0
    typedef union data{
         float a;
         float b;
         int c;
    }data_t;
    int main(int argc ,char **argv)
    {
    
         printf("sizeof(float):%d
    sizeof(data_t):%d
    ",sizeof(float),sizeof(data_t));
         return 0;
    
    
    }
    #endif
    typedef union data{
         int i;
         char x[2];
    }data_t;
    int main(int argc ,char **argv)
    {
    
            data_t datab;
         memset(&datab,0,sizeof(datab));
         datab.x[0] = 10;
         datab.x[1] = 1;
        
            printf("sizeof(float):%d
    sizeof(int):%d
    ",sizeof(float),sizeof(int));
         printf("datab.i :%d
    ",datab.i);
         return 0;
    
    
    }

    4.附录 各个数据类型的长度

    type bytes

    int  4

    char 1

    short int 2

    bool 1

    long 4

    long long 8

    float 4

    double 8

    long double 8

     

    补充1:

    解决一下捧场网友的困惑。

    关于“有名”与“无名”联合体在结构体内所占空间的问题,其实这和是不是结构体无关,只和“有名”、“无名”有关,而且有名无名也是表象,其实是声明类型与定义变量的区别,看例子,直接打印,

    #include <stdio.h>
    struct s1{
            union u{
                    int i;
            };
            struct ss1{
                    int i;
            };
    };
    
    struct s2{
            union{
                    int i;
            };
            struct{
                    int i;
            };
    };
    
    struct s3{//the same to s2
            union su3{
                    int i;
            }su33;
            struct ss3{
                    int i;
            }ss33;
    };
    
    union su4{
            int i;
    };
    struct ss4{
            int i;
    };
    struct s4{//the same to s3
            union su4 su44;
            struct ss4 ss44;
    };
    struct s5{//the same to s1
            union su4;
            struct ss4;
    };
    
    struct s6{//the same to s1
            union{
                    int;
            };
            struct{
                    int;
            };
    };
    
    main(){
            struct s1 sVal1;
            struct s2 sVal2;
            struct s3 sVal3;
            struct s4 sVal4;
            struct s5 sVal5;
            struct s6 sVal6;
    
            printf("sVal1's size:%d
    ",sizeof(sVal1));
            printf("sVal1:%p	%d
    ",&sVal1);
    
            printf("sVal2's size:%d
    ",sizeof(sVal2));
            printf("sVal2:%p	%d
    ",&sVal2);
    
            printf("sVal3's size:%d
    ",sizeof(sVal3));
            printf("sVal3:%p	%d
    ",&sVal3);
    
            printf("sVal4's size:%d
    ",sizeof(sVal4));
            printf("sVal4:%p	%d
    ",&sVal4);
    
            printf("sVal5's size:%d
    ",sizeof(sVal5));
            printf("sVal5:%p	%d
    ",&sVal5);
    
            printf("sVal5's size:%d
    ",sizeof(sVal5));
            printf("sVal5:%p	%d
    ",&sVal5);
    }

    地址供参考,主要看size,分别为:

    0,8,8,8,0,0

    s1只有类型,没有变量,没有变量自然就没有空间占用(s5同)。

    类型就是类型,和是不是结构体、联合体无关的,你的“int i;”中i不就是个变量吗?如果换成int;结果相同(这就是s6)。

    s4和s5的做法能帮助排除干扰,将子结构体与联合体声明在外,内部直接引用,4是定义了变量,5什么都没做。

    另外,这种做法编译的时候GCC会给你在相应的行做出提示“union_with_name.c:49: 警告:没有声明任何东西”

  • 相关阅读:
    关于Unity中Mecanim动画的重定向与动画混合
    php远程抓取网站图片并保存
    OpenResty最佳实践
    111
    安装Nginx+Lua+OpenResty开发环境配置全过程实例
    ecshop常用的一些变量
    php 常用的标签比较
    PHP 设计模式
    mysql导入sql脚本
    linux 解压压缩大全
  • 原文地址:https://www.cnblogs.com/wft1990/p/6700434.html
Copyright © 2011-2022 走看看