首页 > 编程笔记 > C语言笔记(精华版)

C语言union共用体的用法(包括定义、初始化、成员访问、赋值等细节)

共用体(Union)是C语言中一种特殊的数据类型,它允许在同一内存位置存储不同类型的数据。这意味着共用体可以存储多种类型的数据,但在任何给定时刻只能存储其中一种类型的数据。

共用体的这一特性使可以节省内存空间,尤其是在需要在同一内存位置存储不同类型数据的情况下。

要深入理解共用体的概念,我们可以将其想象成一个多功能的容器。这个容器可以存放不同类型的物品,但一次只能存放一种。比如,你有一个盒子,它可以用来存放一本书、一双鞋或者一个水杯。虽然盒子可以容纳所有这些物品,但在任何时候,它只能装其中的一种。共用体就是这样的一个“盒子”,它可以存储不同类型的数据,但在任何时刻只能有一个数据是有效的。
 

共用体的另一个重要特征是内存共享。在共用体中,所有成员共享同一块内存空间,而这块内存的大小由共用体中最大的成员决定。这意味着,无论你存储的是哪种类型的数据,它们都将占用相同的内存空间。这种内存共享机制使得共用体成为一种非常高效的内存使用方式,尤其是在需要频繁切换不同类型数据的场景中。

共用体的定义

共用体的定义和结构体类似,只要把 struct 关键字换成 union 即可,它的语法格式如下:

union 共用体名称 {
    数据类型1 成员1;
    数据类型2 成员2;
    ...
    数据类型n 成员n;
};

这里的union是关键字,用于声明一个共用体。共用体名称是你为这个共用体类型起的名字,而由大括号{ }包围的多个成员,则是这个共用体可以存储的不同类型的数据。


让我们通过一个具体的例子来说明:

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

在这个例子中,我们定义了一个名为 Data 的共用体,它有三个成员:一个整型 i、一个浮点型 f 和一个字符数组 str。这个共用体可以存储一个整数、一个浮点数或者一个字符串,但在任何时刻只有其中一份数据有效。

共用体变量

有了共用体类型,就可以定义变量了。你可以在定义共用体类型的同时定义变量,也可以先定义类型,然后再定义变量。以下是几种定义共用体变量的方式:

// 定义共用体类型的同时定义变量
union Data {
    int i;
    float f;
    char str[20];
} data;

// 先定义类型,然后定义变量
union Data {
    int i;
    float f;
    char str[20];
};
union Data data;

// 定义共用体变量的数组
union Data data_array[10];

和结构体类似,定义共用体变量时前面要加 union 关键字。


共用体变量可以在定义的同时进行初始化,也可以在定义以后再进行赋值。默认情况下,只能初始化第一个成员;如果使用了指定初始化器,那么可以初始化任意一个成员。但是共用体的所有成员都是共享一份内存,所以不管如何,你都只能初始化一个成员,不能初始化多个成员,更不能初始化所有成员。
 

共用体变量初始化的例如:

union Data data = {10};  // 初始化 int i 为 10
union Data data = {.f = 3.14};  // 使用指定初始化器初始化 float f 为 3.14

共用体成员的访问

共用体的成员可以使用点号运算符.或者箭头运算符->来访问。如果是共用体变量,我们就使用点号运算符;如果是共用体指针,我们就使用箭头运算符。这两种运算符在所有表达式中都具有相同的优先级,并且它们的优先级在所有运算符中都是最高的。
 

它们的基本语法格式为:

共用体变量.成员名
共用体指针->成员名

我们通过一个例子来演示:

union Data data;  //共用体变量
union Data *ptr;  //共用体指针

data.i = 10;  //共用体变量通过点号运算符访问成员
printf("整数值:%d\n", data.i);

ptr->f = 3.14;  //共用体指针通过箭头远算符访问成员
printf("浮点数值:%f\n", data.f);

strcpy(data.str, "Hello");
printf("字符串:%s\n", data.str);

需要注意的是,由于共用体的所有成员共享同一块内存,改变一个成员的值会影响其他成员的值。例如,在上面的代码中,当我们通过ptr->f将 f 设置为 3.14 时,data.i 的值也会改变,因为它们共享同一块内存。

共用体的大小

共用体的大小由其最大成员的大小决定,可以使用 sizeof 运算符来获取共用体的大小:

printf("共用体 Data 的大小:%lu 字节\n", sizeof(union Data));

综合示例

下面是一个示例,演示了如何定义和使用共用体,并同时使用点号运算符和箭头运算符:

#include <stdio.h>

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

int main() {
    union Data data;
    union Data *pData = &data;

    //使用点号运算符访问成员
    data.i = 10;
    printf("data.i : %d\n", data.i);
    printf("data.f : %f\n", data.f); //输出的值是未定义的,因为 i 和 f 共享内存

    data.f = 220.5;
    printf("data.i : %d\n", data.i); //输出的值是未定义的,因为 i 和 f 共享内存
    printf("data.f : %f\n", data.f);

    //使用箭头运算符访问成员
    pData->i = 100;
    printf("pData->i : %d\n", pData->i);
    printf("pData->f : %f\n", pData->f); //输出的值是未定义的,因为 i 和 f 共享内存

    pData->f = 123.45;
    printf("pData->i : %d\n", pData->i); //输出的值是未定义的,因为 i 和 f 共享内存
    printf("pData->f : %f\n", pData->f);


    //字符串赋值需要使用 strcpy
    //data.str = "hello";  //错误的赋值方式
    strcpy(data.str, "hello");
    printf("data.str: %s\n", data.str);
    strcpy(pData->str, "world");
    printf("pData->str: %s\n", pData->str);

    return 0;
}

输出结果:

data.i : 10
data.f : 0.000000
data.i : 1091567616
data.f : 220.500000
pData->i : 100
pData->f : 0.000000
pData->i : 1120272384
pData->f : 123.450000
data.str: hello
pData->str: world

总结

共用体是C语言里面一种特殊的数据类型,它允许在同一内存位置存储不同类型的数据。


共用体在某些特定场景下非常有用。例如,当你需要在不同的时间点存储不同类型的数据,但又想节省内存时,共用体就是一个很好的选择。它也常用于处理来自不同数据源的数据,或者在需要对数据进行不同解释的情况下。
 

然而,使用共用体时也需要格外小心。由于共用体的所有成员共享同一块内存,不正确的使用可能导致数据的错误解释或者意外覆盖。因此,在使用共用体时,务必清楚地知道当前存储的是哪种类型的数据,以避免潜在的错误。

相关文章