精华内容
下载资源
问答
  • 联合体

    2017-10-23 22:37:58
    联合体
    1. 联合union是一个能在同一个存储空间存储不同类型数据的类型。

    2. 联合体所占的内存长度等于其最长成员的长度,也有叫做共用体。

    3. 联合体虽然可以有多个成员,但同一时间只能存放其中一种

    4. 对于联合体来讲最基本的原则是,一次只操作一个成员变量,如果这个变量是指针,那么一定是处理完指针对应的内存之后再来使用其他成员。

    这里写图片描述

    union variant{
            int ivalue;
            char cvalue;
            double dvalue;
        };
    
        int main()
        {
            union variant var;
            var.cvalue = 12;
            printf("%d\n", var.ivalue);
            printf("%p, %p, %p\n", &(var.cvalue), &(var.ivalue), &(var.dvalue));
            return 0;
        }
    展开全文
  • java 联合体_联合体

    2021-03-14 23:46:25
    通常以相同的方式为联合体提供标记名称。可以使用关键字union来定义联合体。例如,以下语句声明一个由三个变量共享的联合体:union MyUnion{float my_Float;int *pnum;double my_value;} u1;此语句声明了一个名称为:...

    C语言允许相同的存储区域由许多不同的变量共享。可以使用union类型来进行内存共享。声明union的语法类似于结构。通常以相同的方式为联合体提供标记名称。

    可以使用关键字union来定义联合体。例如,以下语句声明一个由三个变量共享的联合体:

    union MyUnion

    {

    float my_Float;

    int *pnum;

    double my_value;

    } u1;

    此语句声明了一个名称为:MyUnion的联合体,一个浮点值:my_Float,一个指向整数pnum的指针和一个双精度浮点变量my_value之间共享内存。

    该语句定义了一个变量名为u1的union实例。可使用如下语句声明此联合体的其他实例:

    union MyUnion u2, u3;

    要为u1和u2的成员分配值,可以这样写:

    u1.my_Float = 2.5;

    u2.my_Float = 3.5*u1.my_Float;

    union的实例的大小是最大成员所需的内存大小。

    访问联合体成员

    同样,可以以与结构类似的方式访问联合体成员。在上面的示例中,假设要访问union变量car1的price成员,可以使用以下语句:

    car1.price

    同样,如果要访问联合体car3指针变量price,可以这样访问它:

    (*car3).price

    // 或者

    car3->price

    结构体和联合体的区别

    尽管联合体在很多方面与结构体相似,但它们之间的区别对于理解是至关重要的。这个例子说明它们的主要区别:

    #include

    union unionJob

    {

    //defining a union

    char name[32];

    float salary;

    int workerNo;

    } uJob;

    struct structJob

    {

    char name[32];

    float salary;

    int workerNo;

    } sJob;

    int main()

    {

    printf("size of union = %d", sizeof(uJob));

    printf("\nsize of structure = %d", sizeof(sJob));

    return 0;

    }

    执行上面示例代码,得到以下结果:

    size of union = 32

    size of structure = 40

    1. 结构体比联合体需要更多内存

    如上例所示,结构体比联合体之间的内存分配存在差异。存储结构体变量所需的内存量是所有成员的内存大小之和。

    1b9857c70797c9f06d66eda697f99d53.png

    但是,存储union变量所需的内存是union的最大元素所需的内存。

    35b82dd5bc21c578f24c19adf3ee09da.png

    一次只能访问一个联合体成员,在结构体的情况下,可以随时访问其所有成员。

    但是,在union的情况下,一次只能访问其中一个成员,而所有其他成员都将包含垃圾值。

    #include

    union job

    {

    char name[32];

    float salary;

    int workerNo;

    } job1;

    int main()

    {

    printf("Enter name:\n");

    scanf("%s", &job1.name);

    printf("Enter salary: \n");

    scanf("%f", &job1.salary);

    printf("Displaying\nName :%s\n", job1.name);

    printf("Salary: %.1f", job1.salary);

    return 0;

    }

    执行上面示例代码,得到以下结果:

    Enter name

    Hillary

    Enter salary

    1234.23

    Displaying

    Name: f%Bary

    Salary: 1234.2

    注意: name成员的值可能是不同的垃圾值或空字符串。最初在程序中,Hillary存储在job1.name中,job1的所有其他成员,即salary,workerNo,将包含垃圾值。

    但是,当用户输入salary的值时,1234.23将存储在job1.salary中,而其他成员,即name,workerNo,现在将包含垃圾值。因此,在输出中,salary打印准确,但name显示一些随机字符串。

    展开全文
  • 联合体(union)的使用方法及其本质

    万次阅读 多人点赞 2014-04-13 14:27:08
    union,中文名“联合体、共用体”,在某种程度上类似结构体struct的一种数据结构,共用体(union)和结构体(struct)同样可以包含很多种数据类型和变量。 不过区别也挺明显: 结构体(struct)中所有变量是“共存”的.....

    有些基础知识快淡忘了,所以有必要复习一遍,在不借助课本死知识的前提下做些推理判断,温故知新。

     

    1.联合体union的基本特性——和struct的同与不同

    union,中文名“联合体、共用体”,在某种程度上类似结构体struct的一种数据结构,共用体(union)和结构体(struct)同样可以包含很多种数据类型和变量。

    不过区别也挺明显:

    结构体(struct)中所有变量是“共存”的——优点是“有容乃大”,全面;缺点是struct内存空间的分配是粗放的,不管用不用,全分配。

    而联合体(union)中是各变量是“互斥”的——缺点就是不够“包容”;但优点是内存使用更为精细灵活,也节省了内存空间。

     

     

    2.双刃剑——多种访问内存途径共存

     

    一个例子了然:

     

     

    //example
    #include<stdio.h>
    union var{
            long int l;
            int i;
    };
    main(){
            union var v;
            v.l = 5;
            printf("v.l is %d\n",v.i);
            v.i = 6;
            printf("now v.l is %ld! the address is %p\n",v.l,&v.l);
            printf("now v.i is %d! the address is %p\n",v.i,&v.i);
    }
    结果:
    v.l is 5
    now v.l is 6! the address is 0xbfad1e2c
    now v.i is 6! the address is 0xbfad1e2c
    
    

     

    所以说,管union的叫共用体还真是贴切——完全就是共用一个内存首地址,并且各种变量名都可以同时使用,操作也是共同生效。如此多的access内存手段,确实好用,不过这些“手段”之间却没法互相屏蔽——就好像数组+下标和指针+偏移一样。

    上例中我改了v.i的值,结果v.l也能读取,那么也许我还以为v.l是我想要的值呢,因为上边提到了union的内存首地址肯定是相同的,那么还有一种情况和上边类似:

    一个int数组变量a,一个long int(32位机中,long int占4字节,与int相同)变量b,我即使没给int变量b赋值,因为数据类型相同,我使用int变量b也完全会拿出int数组a中的a[0]来,一些时候一不小心用上,还以为用的就是变量b呢~

    这种逻辑上的错误是很难找出来的(只有当数据类型相去甚远的时候稍好,出个乱码什么的很容易发现错误)。

     

    PS:感谢热心网友的提醒“在union定义结束时加分号”,因为最近不关注C,所以我把我的“不加分号也行”改成严谨的“只声明一个union的时候不加也行”,至于为什么C语言有这种不一致的判定,我现在真不关心这种琐碎。

    #include<stdio.h>
    union var{
        long int l;
        int i;
    };
    main(){
        union var v;
        v.l = 5;
        printf("%ld\n",v.l);
        v.i = 6;
    }
    

     

    3.联合体union和大小端(big-endian、little-endian):
    下边示范了一种用途,代表四个含义的四个变量,但是可以用一个int来操作,直接int赋值,无论内存访问(指针大小的整数倍,访问才有效率),还是时间复杂度(一次和四次的区别,而且这四次有三次都是不整齐的地址),都会低一些。

     

    #include<stdio.h>
    union var{
            char c[4];
            int i;
    };
    
    int main(){
            union var data;
            data.c[0] = 0x04;//因为是char类型,数字不要太大,算算ascii的范围~
            data.c[1] = 0x03;//写成16进制为了方便直接打印内存中的值对比
            data.c[2] = 0x02;
            data.c[3] = 0x11;
    //数组中下标低的,地址也低,按地址从低到高,内存内容依次为:04,03,02,11。总共四字节!
    //而把四个字节作为一个整体(不分类型,直接打印十六进制),应该从内存高地址到低地址看,0x11020304,低位04放在低地址上。
            printf("%x\n",data.i);
    }


    结果:
    11020304
    证明我的32位linux是小端(little-endian)

     

     

     

     


    4.联合体union所占内存空间大小:

    前边说了,首先,union的首地址是固定的,那么,union到底总共有多大?根据一些小常识,做个不严谨不高深的基础版验证吧。

    根据:分配栈空间的时候内存地址基本上是连续的,至少同类型能保证在一起,连续就说明,我如果弄三个结构体出来,他们三个地址应该连着,看一下三个地址的间隔就知道了。

    #include<stdio.h>
    union sizeTest{
            int a;
            double b;
    };
    main(){
            union sizeTest unionA;
            union sizeTest unionB;
            union sizeTest unionC;
    
            printf("the initial address of unionA is %p\n",&unionA);
            printf("the initial address of unionB is %p\n",&unionB);
            printf("the initial address of unionC is %p\n",&unionC);
    }

     


    打印,可以看到结果:

    the initial address of unionA is 0xbf9b8df8
    the initial address of unionB is 0xbf9b8e00
    the initial address of unionC is 0xbf9b8e08

    很容易看出,8,0,8,这间隔是8字节,按double走的。

    怕不保险,再改一下,把int改成数组,其他不变:

     

     

     

     

    union sizeTest{
            int a[10];
            double b;
    };

     




    打印

    the initial address of unionA is 0xbfbb7738
    the initial address of unionB is 0xbfbb7760
    the initial address of unionC is 0xbfbb7788

    88-60=28
    60-38=28
    算错了?我说的可是16进制0x。那么0x28就是40个字节,正好是数组a的大小。

     

     

    忘了提一个功能——sizeof()

    用sizeof直接看,就知道union的大小了

     

            printf("the sizeof   of unionA is %d\n",sizeof(unionA));
            printf("the sizeof   of unionB is %d\n",sizeof(unionB));
            printf("the sizeof   of unionC is %d\n",sizeof(unionC));
            printf("the sizeof   of union is %d\n",sizeof(union sizeTest));

     

    上边说的地址规律,没有特定规则,也可能和你的编译器有关。另外,那只是栈空间,还可以主动申请堆空间,当然,堆空间就没有连续不连续一说了。

     


    5.联合体union适用场合:

    有了前边那个验证,基本可以确认,union的内存是照着里边占地儿最大的那个变量分的。

    也就可以大胆的推测一下,这种union的使用场合,是各数据类型各变量占用空间差不多并且对各变量同时使用要求不高的场合(单从内存使用上,我觉得没错)。

    像上边做的第二个测试,一个数组(或者更大的数组int a[100]),和一个或者几个小变量写在一个union里,实在没什么必要,节省的空间太有限了,还增加了一些风险(最少有前边提到的逻辑上的风险)。所以,从内存占用分析,这种情况不如直接struct。

     

    不过话说回来,某些情况下虽然不是很节约内存空间,但是union的复用性优势依然存在啊,比如方便多命名,这种“二义性”,从某些方面也可能是优势。这种方法还有个好处,就是某些寄存器或通道大小有限制的情况下,可以分多次搬运。

     

     

    6.本质&进阶:

     

    根据union固定首地址union按最大需求开辟一段内存空间两个特征,可以发现,所有表面的定义都是虚的,所谓联合体union,就是在内存给你划了一个足够用的空间,至于你怎么玩~它不管~!(何止是union和struct,C不就是玩地址么,所以使用C灵活,也容易犯错)

     

    没错,union的成员变量是相当于开辟了几个访问途径(即union包含的变量)!但是,没开辟的访问方式就不能用了?当然也能用!

    写个小测试:

    #include<stdio.h>
    union u{
            int i;
            double d;//这个union有8字节大小
    };
    main(){
            union u uu;
            uu.i = 10;
            printf("%d\n",uu.i);
    
            char * c;
            c = (char *)&uu;//把union的首地址赋值、强转成char类型
            c[0] = 'a';
            c[1] = 'b';
            c[2] = 'c';
            c[3] = '\0';
            c[4] = 'd';
            c[5] = 'e';
    //最多能到c[7]
            printf("%s\n",c);//利用结束符'\0'打印字符串"abc"
            printf("%c %c %c %c %c %c\n",c[0],c[1],c[2],c[3],c[4],c[5]);
    }

    一个例子了然,我的结构体只定义了int和double“接口”,只要我获得地址,往里边扔什么数据谁管得到?这就是C语言(不止union)的本质——只管开辟一段空间。

     

    但是你获取地址并访问和存取的数据,最好确定是合法(语法)合理(用途符合)的地址,不然虽然能操作,后患无穷,C的头疼之处,可能出了问题你都找不到。

     

     

    最近发现博客盗版严重(尤其是C结构体这篇),允许正规转载,欢迎举报盗版,感谢。博客https://blog.csdn.net/huqinweI987/article/details/23597091

     
     

    ====================================================================================================================================

     

    补充:

     

     

    补充1:

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

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

     

     

     

    #include <stdio.h>
    struct s1{
            union u{
                    int i;
            };
            struct ss1{
                    int i;
            };
    };
     
    struct s2{
            union{
                    int i;
            };
            struct{
                    int i2;
            };
    };
     
    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\n",sizeof(sVal1));
            printf("sVal1:%p\t%d\n",&sVal1,sVal1);
     
            printf("sVal2's size:%d\n",sizeof(sVal2));
            printf("sVal2:%p\t%d\n",&sVal2,sVal2);
     
            printf("sVal3's size:%d\n",sizeof(sVal3));
            printf("sVal3:%p\t%d\n",&sVal3,sVal3);
     
            printf("sVal4's size:%d\n",sizeof(sVal4));
            printf("sVal4:%p\t%d\n",&sVal4,sVal4);
     
            printf("sVal5's size:%d\n",sizeof(sVal5));
            printf("sVal5:%p\t%d\n",&sVal5,sVal5);
     
            printf("sVal6's size:%d\n",sizeof(sVal6));
            printf("sVal6:%p\t%d\n",&sVal6,sVal6);
    }
    

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

     

    0,8,8,8,0,0

     

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

    s2这种写法就是直接定了union和struct。

    s3和s2的区别,只是s2过于简化,s3的意思是既声明了union su3,又定义了这个类型对应的变量su33.

    s4和s5作为对比,为了更好的说明这一点。s5也是纯“贴”表达式,没声明变量。

    s6乍一看类似s2,其实union内部没有具体变量,也是为了做对比的。和s1的不同之处是,一个是外部的union,一个是内部的int,都是干声明不定义,所以没成员,不占用空间。

     

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

     

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

    很多人表示打印结果不一样,我试过很多次,不一样的环境,都是一样的。

     

     

     

    ========================================================================================================================================================================================================================================================================

    以上仅属于个人心得和推测,重点在于学习思维和推理验证过程,不保证正确性与权威性。有兴趣讨论或者有发现错误的,欢迎留言交流指正。

    觉得好的,欢迎转载并注明出处。

    http://blog.csdn.net/huqinwei987/article/details/23597091

    本人博客会根据个人经验升级情况随时补充修改。

     

     

     

    展开全文

空空如也

空空如也

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

联合体