• 联合体


    “联合体”(union)与“结构体”(struct)有一些相似之处。但两者有本质上的不同。在结构体中,各成员有各自的内存空间, 一个结构变量的总长度是各成员长度之和。而在“联合”中,各成员共享一段内存空间, 一个联合变量的长度等于各成员中最长的长度。应该说明的是, 这里所谓的共享不是指把多个成员同时装入一个联合变量内, 而是指该联合变量可被赋予任一成员值,但每次只能赋一种值, 赋入新值则冲去旧值。 一个联合体类型必须经过定义之后, 才能使用它,才能把一个变量声明定义为该联合体类型。 

     

        联合体的定义 定义一个联合类型的一般形式为:  union 联合名 

                                                     { 

                                                       成员表; 

                                                     };

        成员表中含有若干成员,成员的一般形式为: 类型说明符 成员名。成员名的命名应符合标识符的规定。

     例如: 

     union perdata

    {  

     int class;

     char office[10];

    };  

        定义了一个名为perdata的联合类型,它含有两个成员,一个为整型,成员名为class;另一个为字符数组,数组名为office。联合定义之后,即可进行联合变量说明,被说明为perdata类型的变量,可以存放整型量class或存放字符数组office。

        联合体变量的声明:联合变量的说明和结构变量的声明方式相同, 也有三种形式。

        第一种,先定义联合体类型,再声明联合体变量;

        第二种,定义联合体类型的同时声明联合体变量;

        第三种,直接声明联合体(以匿名的形式定义联合体类型)。

        以perdata类型为例,说明如下: 

        第一种,先定义联合体类型,再声明联合体变量

     union perdata

    {    

    int class;  

    char officae[10];

    };

    union perdata a,b;

       第二种,定义联合体类型的同时声明联合体变量: 

     union perdata

     { 

    int class;

    char office[10]; 

     }a,b;

      第三种,直接声明联合体(以匿名的形式定义联合体类型):

      union

    int class;

    char office[10];

    }a,b 

        经说明后的a,b变量均为perdata类型。a,b变量的长度应等于 perdata 的成员中最长的长度, 即等于office数组的长度,共10个字节。对a,b变量如赋予整型值时,只使用了2个字节,而赋予字符数组时,可用10个节。   

        联合体变量的赋值和使用:对联合体变量的赋值,使用都只能是对变量的成员进行。  联合变量的成员表示为: 联合变量名.成员名  例如,a被说明为perdata类型的变量之后,可使用 a.class,a.office  不允许只用联合变量名作赋值或其它操作。 也不允许对联合变量作初始化赋值,赋值只能在程序中进行。 一个联合体变量, 每次只能赋予一个成员值。一个联合变量的值就是联合变员的某一个成员值。为了加深理解,举几个例子:

    例1:

    union myun
    {
     struct {int x; int y; int z; }u;
     int k;
    }a;
    int main()
    {
     a.u.x =4;
     a.u.y =5;
     a.u.z =6;
     a.k = 0;
     printf("%d %d %d ",a.u.x,a.u.y,a.u.z);
     return 0;
    }

        union类型是共享内存的,以size最大的结构作为自己的大小,这样的话,myun这个结构就包含u这个结构体,而大小也等于u这个结构体的大小,在内存中的排列为声明的顺序x,y,z从低到高,然后赋值的时候,在内存中,就是x的位置放置4,y的位置放置5,z的位置放置6,现在对k赋值,对k的赋值因为是union,要共享内存,所以从union的首地址开始放置,首地址开始的位置其实是x的位置,这样原来内存中x的位置就被k所赋的值代替了,就变为0了,这个时候要进行打印,就直接看内存里就行了,x的位置也就是k的位置是0,而y,z的位置的值没有改变,所以应该是0,5,6

         联合体是这么描述的:

         1)联合体是一个结构;

         2)它的所有成员相对于基地址的偏移量都为0;

         3)此结构空间要大到足够容纳最"宽"的成员;

         4)其对齐方式要适合其中所有的成员;

    下面解释这四条描述:

         由于联合体中的所有成员是共享一段内存的,因此每个成员的存放首地址相对于于联合体变量的基地址的偏移量为0,即所有成员的首地址都是一样的。为了使得所有成员能够共享一段内存,因此该空间必须足够容纳这些成员中最宽的成员。对于这句“对齐方式要适合其中所有的成员”是指其必须符合所有成员的自身对齐方式。

    下面举例说明:

     例2:

    union U
    {
        char s[9];
        int n;
        double d;
    };

        s占9字节,n占4字节,d占8字节,因此其至少需9字节的空间。然而其实际大小并不是9,用运算符sizeof测试其大小为16.这是因为这里存在字节对齐的问题,9既不能被4整除,也不能被8整除。因此补充字节到16,这样就符合所有成员的自身对齐了。从这里可以看出联合体所占的空间不仅取决于最宽成员,还跟所有成员有关系,即其大小必须满足两个条件:1)大小足够容纳最宽的成员;2)大小能被其包含的所有基本数据类型的大小所整除。

  • 相关阅读:
    三、ADO.Net基础【04】简单查询
    Canvas 图片绕边旋转的小动画
    Canvas 剪切图片
    Canvas 图片平铺设置
    Canvas 给图形绘制阴影
    Canvas 图形组合方式
    [转]JS获取URL传参方法
    HTML5 FileReader接口学习笔记
    css3实现圆角边框渐变
    HTML5新增属性学习笔记
  • 原文地址:https://www.cnblogs.com/wgang171412/p/5008163.html
Copyright © 2020-2023  润新知