定义:与结构体一样,只要将struct变成union即可
存储空间:只创造一个存储空间,空间大小为最大成员的大小,可以被所有成员所用,但一次只能被一个成员所用,这个空间相对与一个公共的空间,但容纳的具有唯一性,即一次只能容纳一个成员,而且是由最新被赋予值的成员使用,一旦某个成员被赋予了新值,则此成员的新值将替代掉前一个成员占据此空间。但是作为成员引用的话,若是空间存的是另一个成员的值,但因为内存本身没有类型的原则,则是根据访问的类型来取长度,所以用其它成员来访问这个成员在空间里的值也是可以的,只是对于这个成员本身来说就不是它自己的值了。
初始化方式:只能用与第一个成员类型相同的值来初始化,而不能用其它成员类型的值。
引用方式:与结构体不同,不能对共用体变量进行直接引用,只能对成员进行引用,而结构体变量则可以用于赋值、函数参数,这些联合变量都不可以。只能通过对成员的引用。
联合体与结构体位域:可以实现读取一个变量的二进制位或字节(8个位)的内容。
<pre name="code" class="vb">
#include <stdio.h>
typedef union abc{
int a;
float b;
char c;
}abc;
int main(void)
{
abc m = { 65 };
abc n = {'B'}; //不合法,但仍可以用
abc k = {19.65};//不合法,但仍可以用
printf("%d %c\n",m.a,m.c);
printf("%d %c\n",n.a,n.c);
printf("%d %f\n",k.a,k.b);
m.b = 10.20;
printf("%d %f %c\n",m.a,m.b,m.c);
return 0;
}
结果:
65 A
66 B
19 0.000000
1092825907 10.200000 3
定义
在进行某些算法的C语言编程的时候,需要使几种不同类型的变量存放到同一段内存单元中。也就是使用覆盖技术,几个变量互相覆盖。这种几个不同的变量共同占用一段内存的结构,在C语言中,被称作“共用体”类型结构,简称共用体。
一般定义形式,与结构体一样,只要将struct变成union即可:
union 共用体名
{
成员表列
}变量表列;
简单示例
union data
{
int i;
char ch;
float f;
}a,b,c;
编辑本段
共用体变量的引用方式、初始化方式:
只有先定义了共用体变量才能在后续程序中引用它,有一点需要注意:不能引用共用体变量,而只能引用共用体变量中的成员。但可以有指向变量的指针
只能用与第一个共用体成员的类型相同的值进行初始化
简单示例
union data
{
int i;
char ch;
float f;
}a,b,c;
对于这里定义的共用体变量a,b,c。下面的引用方式是正确的:
a.i (引用共用体变量中的整型变量i)
a.ch (引用共用体变量中的字符变量ch)
a.f (引用共用体变量中的实型变量f)
而不能引用共用体变量,例如:
printf("%d",a); <==这种用法是错误的。
因为a的存储区内有好几种类型的数据,分别占用不同长度的存储区,这些共用体变量名a,难以使系统确定究竟输出的是哪一个成员的值。
而应该写成
printf("%d",a.i); 或 printf("%c",a.ch);
对于这里定义的共用体变量,下面的初始化方式是正确的:
union data m = 20;
而下面的则是非法的:
union data n = 'c' 或 union data n = 13.8都是错误的!
编辑本段
共用体类型数据的特点
1.同一个内存段可以用来存放几种不同类型的成员,但是在每一瞬间只能存放其中的一种,而不是同时存放几种。换句话说,每一瞬间只有一个成员起作用,其他的成员不起作用,即不是同时都在存在和起作用。
2.共用体变量中起作用的成员是最后一次存放的成员,在存入一个新成员后,原有成员就失去作用。
3.共用体变量的地址和它的各成员的地址都是同一地址。
4.不能对共用体变量名赋值,也不能企图引用变量名来得到一个值,并且,不能在定义共用体变量时对它进行初始化。
5.不能把共用体变量作为函数参数,也不能是函数带回共用体变量,但可以使用指向共用体变量的指针。
6.共用体类型可以出现在结构体类型的定义中,也可以定义共用体数组。反之,结构体也可以出现在共用体类型的定义中,数组也可以作为共用体的成员。
结构体和共用体的区别
如果暂且把结构体变量在内存中占据的空间理解为其各个成员变量长度的简单叠加的话,那么共用体的大小取决于其成员变量中占据空间最大的数据类型。
联合体与结构体位域:可以实现读取一个变量的二进制位或字节(8个位)的内容。
//方法一:用字节访问内存的方法,但最小只能以字节为内存单位
#if 1
union byte
{
struct //因为只是要定义一个位域结构体变量,而类型名不需要知道,所以可以可以不取类型名
{
char x1:8;//也可以去掉unsigned ,不受影响的!
char x2:8;
char x3:8;
char x4:8;
}tb;
unsigned int a;
}tmp;
#include<stdio.h>
int main()
{
int a = 16777230;
printf("%#x %#x %#x %#x\n",((char *)&a)[0],((char *)&a)[1],((char *)&a)[2],((char *)&a)[3]);//从低字节到高字节
printf("%p %p %p %p\n",(char *)&a,(char *)&a+1,(char *)&a+2,(char *)&a+3); //显示低字节到高字节的地址
tmp.a = a;
printf("x1=%d \nx2=%d \nx3=%d \nx4=%d\n",tmp.tb.x1,tmp.tb.x2,tmp.tb.x3,tmp.tb.x4);
return 0;
}
/*
0xe 0 0 0x1
0xbfc2493c 0xbfc2493d 0xbfc2493e 0xbfc2493f
x1=14
x2=0
x3=0
x4=1
*/
#endif
//方法二:将位域与联合体合用,最小可以以1 个二进制位为内存单位
#if 0
#include<stdio.h>
union bit
{
struct
{
unsigned char x1:2; //也可以去掉unsigned ,不受影响的!
unsigned char x3:2;
unsigned char x2:2;
unsigned char x4:2;
}cn;
unsigned char s;
} tmp;
int main()
{
//位域+联合体
tmp.s = 173; //二进制形式是10101110
printf("tmp.s is %d\n",tmp.s);
printf("x1 is %d\n",tmp.cn.x1);
printf("x2 is %d\n",tmp.cn.x2);
printf("x3 is %d\n",tmp.cn.x3);
printf("x4 is %d\n",tmp.cn.x4);
//位操作符
char t = tmp.s;
int i = 8;
while(i--)
{
printf("%d",t>0? 0:1);
t<<=1;
}
printf("\n");
return 0;
}
/*
输出结果:
tmp.s is 173
x1 is 1
x2 is 3
x3 is 2
x4 is 2
10101101
//x4 x3 x2 x1 即是: 10101110
*/
#endif