C语言之union共同体

C语言之union共同体

文章链接

知识点

  1. union共同体的定义;
  2. union空间长度的分配;
  3. 共同体个变量相互影响及原因;
  4. union的使用样例;
  5. 新名词记录{union共同体;Unicode;}

概述

在C语言中,给我们提供了分配和操作一块内存的方式,那就是union关键字。union关键字,定义union下面的成员变量共享一块内存,每一个成员在任一时刻有且只有一个成员使用此块内存。

因为C语言只管分配一段空间,至于里面放什么内容,系统都不会管。结构体strcut也是如此。

定义

下面直接看如何定义union共同体。共同体是会按照成员中最大的一个数据长度分配空间。

union data{
    int i;
    double d;
    char str[20];
};

解释:在上面的共同体中,定义了3个成员,i占用4个字节,d占用8个字节,而str则占用20个字节,所以data的空间长度是20个字节。

data共同体名字可以不写,而在最后面也可以加入union的名字,创建union的同时,创建union变量,这个写法和strcut是一样的。eg

union data{
    int i;
    double d;
    char str[20];
}d1, d2;
d1.i = 11;
d2.i = 12;

因为有20个字节的空间,里面放入什么内容,取决于我们。例如下面的例子

union u uu;  
uu.i = 10;  
printf("%d\n",uu.i); //输出10
//下面根据每个字节放入字符
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[19]

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]);
//分别输出a, b, c,  , d, e ,\0输出为空格

可以在上面看到,我们其实分别在第一个,第二个…等字节中存入了小写字符的值,然后输出每个字节,那么对应的就是每个代表的字符了。


union空间大小分配

那么union的分配是按照怎样的规则来分配的呢?
我们看下面的例子。

/**
 * union分配空间大小说明
 */
void unionSizeTest()
{
    union sizeTest{  
        int a;  
        double b;  
    }; 
    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);  
    //证明union分配的空间其实是连续分配的
    /**
     * the initial address of unionA is 0x7fff53801b08 140734594292488
the initial address of unionB is 0x7fff53801b00 140734594292480
the initial address of unionC is 0x7fff53801af8 140734594292472
     */
}

从打印的结果可以看出,a和b的地址差了0x08,而b和c之间也是差了0x8,可以看到相邻的两个union变量的空间长度都间隔8个字节。而这个字节则是double变量b的存储大小。因此,这里可以知道,union分配空间是,是按着最大的变量来进行分配的。


赋值错乱问题

如果定义了几个变量,但是在没有使用之前,就重新赋值,那么前后的值就会有覆盖。具体问题如下所示。

void unitTest(){
    union Data{
        int i;
        float f;
        char str[20];
    };
    union Data data;
    data.i = 10;
    printf("data.i=%d\n", data.i);

    data.f = 225.6;
    printf("data.f=%f\n",data.f);

    strcpy(data.str, "tanksu");
    printf("data.str=%s\n", data.str);

    //如果直接全部赋值,那么里面的值就有损坏
    //如下代码
    /**
     * data.i = 10;
   data.f = 220.5;
   strcpy( data.str, "C Programming");
     * 
     * 输出:
     * data.i : 1917853763
data.f : 4122360580327794860452759994368.000000
data.str : C Programming
     */
}

上面的结果可以看出来:共用体成员之间会相互影响,修改一个成员的值会影响其他成员。

那么这是如何来影响的呢?
这个共同体需要的空间长度为20个字节,那么我们填充i,只需要填充前面4个字节,而填充f,则需要前面8个字节,但是如果我填充str,则取药填充20个字节。一句话来说,填充f,会影响i;填充str,则会影响i和f。

那么就可以知道,在我们填充了C Programming字串之后,i只需要前4位的字节,f需要前8位的字节。那么取出来对应的Unicode码对应的字符应该就不是前面赋值给i和f对应的字符了。那么导致的原因也就出来了。


共同体应用

(来自http://c.biancheng.net/cpp/html/2932.html)

一个实例是: 现有一张关于学生信息和教师信息的表格。学生信息包括姓名、编号、性别、职业、分数,教师的信息包括姓名、编号、性别、职业、教学科目。

f 和 m 分别表示女性和男性,s 表示学生,t 表示教师。

如果把每个人的信息都看作一个结构体变量的话,那么教师和学生的前 4 个成员变量是一样的,第 5 个成员变量可能是 score 或者 course。当第 4 个成员变量的值是 s 的时候,第 5 个成员变量就是 score;当第 4 个成员变量的值是 t 的时候,第 5 个成员变量就是 course。

#include <stdio.h>
#include <stdlib.h>
#define TOTAL 4  //人员总数
struct{
    char name[20];
    int num;
    char sex;
    char profession;
    union{
        float score;
        char course[20];
    } sc;
} bodys[TOTAL];
int main(){
    int i;
    //输入人员信息
    for(i=0; i<TOTAL; i++){
        printf("Input info: ");
        scanf("%s %d %c %c", bodys[i].name, &(bodys[i].num), &(bodys[i].sex), &(bodys[i].profession));
        if(bodys[i].profession == 's'){  //如果是学生
            scanf("%f", &bodys[i].sc.score);
        }else{  //如果是老师
            scanf("%s", bodys[i].sc.course);
        }
        fflush(stdin);
    }
    //输出人员信息
    printf("\nName\t\tNum\tSex\tProfession\tScore / Course\n");
    for(i=0; i<TOTAL; i++){
        if(bodys[i].profession == 's'){  //如果是学生
            printf("%s\t%d\t%c\t%c\t\t%f\n", bodys[i].name, bodys[i].num, bodys[i].sex, bodys[i].profession, bodys[i].sc.score);
        }else{  //如果是老师
            printf("%s\t%d\t%c\t%c\t\t%s\n", bodys[i].name, bodys[i].num, bodys[i].sex, bodys[i].profession, bodys[i].sc.course);
        }
    }
    return 0;
}
/*
运行结果:
Input info: HanXiaoXiao 501 f s 89.5↙
Input info: YanWeiMin 1011 m t math↙
Input info: LiuZhenTao 109 f t English↙
Input info: ZhaoFeiYan 982 m s 95.0↙

Name            Num     Sex     Profession      Score / Course
HanXiaoXiao     501     f       s               89.500000
YanWeiMin       1011    m       t               math
LiuZhenTao      109     f       t               English
ZhaoFeiYan      982     m       s               95.000000
*/

总结

上面讲到了union共同体的定义,如何分配空间,以及变量之间赋值错乱的导致原因。其实最主要的还是要理解union的空间分配以及基本数据类型占用的存储字节数。最后引用了一个union使用的例子,方便理解。

以上就是所有内容,如有任何问题,请及时与我联系。谢谢

  • 21
    点赞
  • 88
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值