C语言联合体(union)的定义、初始化和使用
在C语言中,可以定义不同数据类型的数据共占同一段内存空间,以满足某些特殊的数据处理要求,这种数据构造类型就是联合体。
联合体的所有成员在内存中具有相同的首地址,共占同一段内存空间,这些成员可以相互覆盖,因此联合体也常常被称作共用体,在不同的时间保存不同的数据类型和不同长度的成员的值。也就是说,在某一时刻,只有最新存储的成员是有效的。运用此种类型数据的优点是节省存储空间。
联合体类型定义的一般形式为:
联合体类型名是一个合法的C语言标识符,联合体类型成员的数据类型可以是C语言中的任何一个基本数据类型,最后的分号表示联合体定义的结束。例如:
说明:联合体类型的定义只是由用户构造了一个联合体,定义好后可以像C中提供的基本数据类型一样被使用,即可以用它来定义变量。但定义联合体类型时,系统并不为其分配存储空间,而是为由该联合体类型定义的变量分配存储空间。
由于此联合体没有标识符,所以无法采用定义联合体变量的第 1 种方法来定义变量。在实际应用中,此方法适合于临时定义局部使用的联合体类型变量。说明如下。
这是因为和结构体变量的存储结构不同,联合体变量中的成员是共用一个首地址,共占同一段内存空间,所以在任意时刻只能存放其中一个成员的值。
也就是说,每一瞬时只能有一个成员起作用,所以,在对联合体类型的变量定义并初始化时,只能是对第 1 个成员赋初值,初值需要用 “{}” 括起来。
【示例1】联合体类型的应用举例。代码入下:
赋初值十六进制的 974161 进行初始化后的存储情况如图所示。
输出时,a.u1 输出它得到的初始值 0x974161,以十进制长整型输出 9912673;a.u2 并没有得到初值,但由于它和 a.u1 共用首地址,共用内存,所以在输出时,它取其中低位的一个字节 01100001,并把它以字符“a”的形式输出。
再把【示例1】的程序稍作改动,即把联合体中的第 1 个成员 u1 定义为字符型,把 u2 定义为长整型。
【示例2】联合体类型的应用举例。代码入下:
赋初值进行初始化后,由于第 1 个成员是字符型,仅用 1 个字节,所以初值十六进制的 974161 只能接受 0x61,其他高位部分被舍去。存储情况如下图所示。
输出时,a.u1 输出它得到的初始值 0x61,以字符的形式输出 “a”;a.u2 并没有得到初值,但由于它和 a.u1 共用首地址,共用内存,所以在输出时,以十进制长整型输出 97。
请认真比较以上两个示例。
【示例3】联合体变量引用的应用举例。代码入下:
声明:《C语言系列教程》为本站“54笨鸟”官方原创,由国家机构和地方版权局所签发的权威证书所保护。
C语言联合体类型的定义
联合体也是一种构造数据类型,和结构体类型一样,它也是由各种不同类型的数据组成,这些数据叫作联合体的成员。不同的是,在联合体中,C语言编译系统使用了覆盖技术。联合体的所有成员在内存中具有相同的首地址,共占同一段内存空间,这些成员可以相互覆盖,因此联合体也常常被称作共用体,在不同的时间保存不同的数据类型和不同长度的成员的值。也就是说,在某一时刻,只有最新存储的成员是有效的。运用此种类型数据的优点是节省存储空间。
联合体类型定义的一般形式为:
union 联合体名
{
数据类型1 成员名1;
数据类型2 成员名2;
…
数据类型n 成员名n;
};
联合体类型名是一个合法的C语言标识符,联合体类型成员的数据类型可以是C语言中的任何一个基本数据类型,最后的分号表示联合体定义的结束。例如:
union ucode
{
char u1;
int u2;
long u3;
};
说明:联合体类型的定义只是由用户构造了一个联合体,定义好后可以像C中提供的基本数据类型一样被使用,即可以用它来定义变量。但定义联合体类型时,系统并不为其分配存储空间,而是为由该联合体类型定义的变量分配存储空间。
C语言联合体变量的定义
在一个程序中,一旦定义了一个联合体类型,也就可以用这种数据类型定义联合体变量。和定义结构体变量一样,定义联合体类型变量的方法有以下 3 种。1) 定义联合体类型后定义变量
一般形式如下。
union 联合体名
{
数据类型1 成员名1;
数据类型2 成员名2;
…
数据类型n 成员名n;
};
2) 定义联合体类型的同时定义变量
一般形式如下。
union 联合体名
{
数据类型1 成员名1;
数据类型2 成员名2;
…
数据类型n 成员名n;
} 变量名1, 变量名2, … , 变量名n;
3) 直接定义联合体类型变量
这种定义方式是不指出具体的联合体类型名,而直接定义联合体成员和联合体类型的变量。一般形式如下。
union
{
数据类型1 成员名1;
数据类型2 成员名2;
…
数据类型n 成员名n;
} 变量名1, 变量名2, … , 变量名n;
由于此联合体没有标识符,所以无法采用定义联合体变量的第 1 种方法来定义变量。在实际应用中,此方法适合于临时定义局部使用的联合体类型变量。说明如下。
- 当一个联合体变量被定义后,编译程序会自动给变量分配存储空间,其长度为联合体的数据成员中所占内存空间最大的成员的长度。
- 联合体可以嵌套定义,即一个联合体的成员可以是另一个联合体类型的变量;另外,联合体和结构体也可以相互嵌套。
C语言联合体变量的初始化
定义联合体变量的同时对其成员赋初值,就是对联合体变量的初始化。那么,对联合体变量初始化可以和结构体变量一样,在定义时直接对其各个成员赋初值吗?看看下面的这段程序代码。union ucode { char u1; int u2; }; /*定义联合体类型*/ union ucode a={'a',45}; /*定义联合体类型的变量a并初始化*/编译时却提示错误信息 “too many initializers”,这是为什么?
这是因为和结构体变量的存储结构不同,联合体变量中的成员是共用一个首地址,共占同一段内存空间,所以在任意时刻只能存放其中一个成员的值。
也就是说,每一瞬时只能有一个成员起作用,所以,在对联合体类型的变量定义并初始化时,只能是对第 1 个成员赋初值,初值需要用 “{}” 括起来。
【示例1】联合体类型的应用举例。代码入下:
#include "stdio.h" int main() { union { long u1; char u2; } a={0x974161}; /*定义联合体类型的变量a*/ printf("%ld %c\n",a.u1,a.u2); }运行结果:
9912673 a
程序中定义的联合体类型包含两个成员 u1 和 u2,分别是 4 个字节的长整型和 1 个字节的字符型,编译系统会按其中占用空间较多的长整型变量给联合体类型的变量 a 分配 4 个字节的存储空间。赋初值十六进制的 974161 进行初始化后的存储情况如图所示。

输出时,a.u1 输出它得到的初始值 0x974161,以十进制长整型输出 9912673;a.u2 并没有得到初值,但由于它和 a.u1 共用首地址,共用内存,所以在输出时,它取其中低位的一个字节 01100001,并把它以字符“a”的形式输出。
再把【示例1】的程序稍作改动,即把联合体中的第 1 个成员 u1 定义为字符型,把 u2 定义为长整型。
【示例2】联合体类型的应用举例。代码入下:
#include "stdio.h" int main() { union ucode { char u1; long u2; }a={0x974161}; printf("%c %ld\n",a.u1,a.u2); }运行结果:
a 97
程序中定义的联合体类型包含两个成员 u1 和 u2,分别是 1 个字节的字符型和 4 个字节的长整型,编译系统会按其中占用空间较多的长整型变量给联合体类型的变量 a 分配 4 个字节的存储空间。赋初值进行初始化后,由于第 1 个成员是字符型,仅用 1 个字节,所以初值十六进制的 974161 只能接受 0x61,其他高位部分被舍去。存储情况如下图所示。

输出时,a.u1 输出它得到的初始值 0x61,以字符的形式输出 “a”;a.u2 并没有得到初值,但由于它和 a.u1 共用首地址,共用内存,所以在输出时,以十进制长整型输出 97。
请认真比较以上两个示例。
C语言联合体变量的引用
联合体变量不能整体引用,对联合体变量的赋值、使用都只能对变量的成员进行,联合体变量引用其成员的方法与访问结构体变量成员的方法相同。例如:
union ucode
{
char u1;
int u2;
long u3;
};
uion ucode a;
a.u1, a.u2
【示例3】联合体变量引用的应用举例。代码入下:
#include "stdio.h" int main() { union ucode /*定义联合体类型*/ { char u1; int u2; }; union ucode a; /*定义联合体类型的变量*/ a.u2=5; printf("输入a.u1的值:\n"); /*提示信息*/ scanf("%d",&a.u1); printf("输出数据:\n"); printf("%c\n",a.u1); /*提示信息*/ printf("%d\n",a.u2); }运行结果:
输入a.u1的值:
65
输出数据:
A
65
- 第 09 行定义联合体类型变量 a;
- 第 10 行对 a 中的 u2 成员即 a.u2 赋值 5;
- 接着又通过 scanf 语句对 a.u1 赋值,从键盘输入 1 个字符的 ASCII 码值,这里运行时输入了 65;
- 那么第12行的输出结果即是此时a中有效的成员 a.u1 的值,输出字母 A;
- 第 13 行 a.u2 尽管没有实际意义,但由于它和 a.u1 共用一个首地址,且占用相同的存储空间,所以输出的结果是整数 65。
声明:《C语言系列教程》为本站“54笨鸟”官方原创,由国家机构和地方版权局所签发的权威证书所保护。