C语言知识总结——共用体

union 共用体(联合体)

在进行某些算法的C语言编程的时候,需要使几种不同类型的变量存放到同一段内存单元中。也就是使用覆盖技术,几个变量互相覆盖。这种几个不同的变量共同占用一段内存的结构,在C语言中 以关键字union声明的一种数据结构,这种被称作“共用体”类型结构,也叫联合体。

“联合”与“结构”有一些相似之处。但两者有本质上的不同。在结构中各成员有各自的内存空间,一个结构体变量的总长度大于等于各成员长度之和。而在“联合”中,各成员共享一段内存空间,一个联合变量的长度等于各成员中最长的长度。注意这里所谓的共享不是指把多个成员同时装入一个联合变量内,而是指该联合变量可被赋予任一成员值,但每次只能赋一种值,赋入新值则冲去旧值,共用体变量中起作用的成员是最后一次存放的成员,在存入一个新成员后,原有成员就失去作用,共用体变量的地址和它的各成员的地址都是同一地址

  • 一个联合类型必须经过定义之后,才能把变量说明为该联合类型:

联合的定义:
定义一个联合类型的一般形式为:
union [name](联合名)   name是可选的
{
成员表
};
成员表中含有若干成员,成员的一般形式为: 类型说明符 成员名
成员名的命名应符合标识符的规定。

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


现在 Data所有的成员共享一个空间,同一时间只有一个成员是的值有效的,Data 类型的变量可以存储一个整数、
一个浮点数,或者一个字符串。这意味着一个变量(相同的内存位置)可以存储多个多种类型的数据。
您可以根据需要在一个共用体内使用任何内置的或者用户自定义的数据类型。
共用体占用的内存应足够存储共用体中最大的成员。例如,在上面的实例中,
Data 将占用 20 个字节的内存空间,因为在各个成员中,字符串所占用的空间是最大的。

注意:1、不能把共用体变量作为函数参数,也不能是函数带回共用体变量,但可以使专用指向共用体变量的指针

2、所有成员占用同一段内存,修改一制个成员会影响其余所有成员。

  • 共用体的访问:共用体访问成员的值时一般使用.运算符,指针时用->运算符(和结构体是一样的)

typedef union _node {
 int a;
 double b;
 char c;
 union _node *p;

}NODE;

int main(void) {

 NODE a;//定义变量
 NODE t;
 a.b;//用.访问
 t.p->a;//指针用->访问



}
联合的使用规则几乎和结构体strtct的规则用法一样,只不过是内部表示的不同。

补充:
还有一个是无名联合体,它是和无名结构体的工作原理是相同的
#include//简单的例子
#include

typedef union _node{
 int a;
 double b;
 char c[20];

}NODE;

int main(void) {

 NODE a;//这里只定义一个变量

 a.a = 666;
 printf("%d\n", a.a);

 a.b = 9.99;
 printf("%f\n", a.b);

 strcpy(a.c, "hello world!");
 printf("%s\n", a.c);

 //我们看到,三个都被完整的输出了,因为在同一时刻,只有一个成员是有效的

}

输出:
666
9.990000
hellow world!
  • 共用体的作用:

    1、节省内存,有两个很长的数据结构,不会同时使用,比如一个表示老师,一个表示学生,如果要统计教师和学生的情况用结构体的话就有点浪费了!用结构体的话,只占用最长的那个数据结构所占用的空间,就足够了!

    2、实现不同类型数据之间的类型转换,遇到各种类型的数据共用存储空间,很方便的实现了不同数据类型之间的转换,不需要显示的强制类型转换。

    其他:1、确定CPU的模式:大端、小端模式确定

    大小端不同,则存储的方式也存在差别,比如int需要4个字节,而char只需要1个字节,根据1个字节所在的具体位置即可判定CPU的模式

    2、寄存器的定义,实现整体的访问和单项的访问

//共用体综合例子:根据输入的数据类型输出需要的相应的数据
#include
#include//数据类型输出   5*4  m n     n的第几个x 

union node {
 int a;
 double b;
 char c[30];

}add[10000];

char p[10000][30]; //保存的字符串数组

int main(void) {
 int n, m;
 scanf("%d %d", &n, &m);
 int x;
 double y;
 char t[50];
 int i, j;

 for (i = 0; i < n; i  ) {//输入
  scanf("%s", &p[i]);//作为字符串数组,需要取地址

  if (strcmp("INT", p[i]) == 0) {//整形
   scanf("%d", &x);
   add[i].a = x;
  }
  else if(strcmp("DOUBLE",p[i])==0){//浮点
   scanf("%lf", &y);
   add[i].b = y;
  }
  else if (strcmp("STRCING", p[i]) == 0) {//字符串
   scanf("%s", t);
   strcpy(add[i].c, t);
  }

 }

 for (i = 0; i < m; i  ) {//输出
  scanf("%d", &j);

  if (strcmp("INT", p[j]) == 0) {
   printf("%d\n", add[j].a);
  }
  else if (strcmp("DOUBLE", p[j]) == 0)
  {
   printf("%f\n", add[j].b);
  }else if(strcmp("STRING",p[j])==0)
  {
   printf("%s\n", add[j].c);

  }

 }

 return 0;

}

//输入:
/*
5 4
INT 456
DOUBLE 123.56
DOUBLE 0.476
STRING welcomeToC
STRING LemonTree
0
1
2
4
*/

//输出:
/*
456
123.56
0.48
LemonTree
*/

声明:

本文于网络整理,版权归原作者所有,如来源信息有误或侵犯权益,请联系我们删除或授权事宜。

f387a012ee2dc96d96996b6a4d6e8fb9.png

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值