C 联合体

C 联合体类型简介

在 C 语言中,联合体也是一种用户自定义的数据类型(与结构体类似)。它可以包含多个不同类型的成员。

语法:

union 类型名
{
    类型1  成员名1;
    类型2  成员名2;
    ……
    类型n  成员名n;
};

说明:

union 是定义联合体的关键字。“类型名” 是联合体的名称,该名字是可以省略的。然后大括号 “{}” 中声明了联合体的成员,每个成员都有自己的类型和名称。

联合体的所有成员共享同一块内存空间,该内存空间的大小由联合体中占用内存最多的成员决定。与结构体类似,定义联合体类型时,大括号后面的分号不能省略。

使用联合体的主要目的是节省内存。当需要存储多种不同类型的数据,但同一时间只需要使用其中一种时,联合体可以有效地利用内存。

注意: 结构体中每个成员都拥有独立的内存空间,而联合体的所有成员共享同一块内存空间。这意味着在任何给定的时间,联合体中只有一个成员是活动的。

示例 1:联合体的基本用法

#include <stdio.h>
#include <string.h>

// 定义一个联合体类型
union Data 
{
    int i;
    float f;
    char str[20];
};

int main(void) 
{
    // 定义一个联合体变量
    union Data data;

    // 存储整数
    data.i = 666;
    printf("%d\n",data.i);

    // 存储浮点数 (会覆盖之前的整数值)
    data.f = 3.14;
    printf("%f\n", data.f);

    // 存储字符串 (会覆盖之前的浮点数值)
    strcpy(data.str, "lvyenet");
    printf("%s\n", data.str);

    return 0;
}

运行结果如下。

666
3.140000
lvyenet

分析:

在上面例子中,我们使用 union 关键字定义了一个名为 Data 的联合体类型。Data 联合体包含 3 个成员:一个 int 类型的 i,一个 float 类型的 f,以及一个 char 数组 str。

main 函数 中,定义了一个 Data 类型的联合体变量 data。我们先将整数 666 赋值给 data.i 并打印出来,然后将浮点数 3.14 赋值给 data.f。此时,之前存储在同一内存位置的整数值就被覆盖了。最后,我们使用 strcpy() 函数将字符串 "lvyenet" 复制到 data.str 中。同样地,之前存储的浮点数值也被覆盖了。

从这个例子,我们可以非常直观地理解了联合体的特性,也就是:所有成员共享同一块内存空间,在任何时候只有一个成员的值是有效的

C 定义联合体变量

在 C 语言中,定义联合体变量的方式与定义结构体变量类似,主要有以下 3 种方式。

1. 先定义类型,后定义变量

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

union Data data;

2. 定义类型的同时定义变量(带类型名)

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

3. 定义类型的同时定义变量(不带类型名)

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

与结构体类似,第 3 种方式在实际开发中很少会使用。

C 访问联合体变量

在 C 语言中,访问联合体成员的方式与访问结构体成员完全相同,都是使用点运算符 (.)。

语法:

联合体变量名.成员名

示例 2:访问联合体成员

#include <stdio.h>
#include <string.h>

union Student 
{
    char name[20];
    int age;
    float score;
};

int main(void) 
{
    union Student stu;

    strcpy(stu.name, "阿莫");
    printf("name: %s\n", stu.name);

    stu.age = 20;
    printf("age: %d\n", stu.age);

    return 0;
}

运行结果如下。

name: 阿莫
age: 20

分析:

上面例子定义了一个 Student 联合体,它可以存储学生的姓名(字符串)、年龄(整数)或分数(浮点数)。我们首先存储了学生的姓名,并将其打印出来。然后,我们存储了年龄,并再次打印出来。需要注意的是,当我们存储年龄时,之前存储的姓名已经被覆盖了。

C 联合体的大小

在 C 语言中,联合体的大小是其最大的成员所占用的内存大小。这是因为联合体的所有成员共享同一块内存空间,这块空间必须足够容纳最大的成员。

示例 3:获取联合体的大小

#include <stdio.h>

union Data 
{
    int a;
    double b;
    char c[20];
};

int main(void) 
{
    union Data data;
    printf("联合体大小: %lu bytes\n", sizeof(data));
    return 0;
}

运行结果如下。(不同系统的结果可能不一样)

联合体大小: 24 bytes

分析:

在这个例子中,Data 联合体包含一个 int ( 通常 4 字节 ), 一个 double ( 通常 8 字节 ), 和一个 char 数组 (20 字节 )。由于 char 数组 c 占用 20 个字节,是联合体最大的成员。

这里小伙伴们就会问了:“为什么打印结果不是 20,而是 24 呢?”。这是因为联合体的大小通常需要对齐到最大成员的对齐要求。在大多数系统中,double 的对齐要求是 8 字节,因此联合体的大小会被对齐到 24 字节(因为 20 不是 8 的倍数,需要补齐到 24)。

C 联合体的应用场景

在实际开发中,C 联合体在以下情况下非常有用:

  • 节省内存:当需要在同一内存位置存储不同类型的数据,但同一时间只需要使用其中一种时,可以使用联合体来节省内存空间。
  • 类型转换:联合体可以用于进行低级别的类型转换,尽管这种做法需要谨慎,因为它可能导致不可移植的行为。
  • 数据表示:当需要以多种不同的方式解释同一块内存数据时,可以使用联合体。例如,一个 32 位的整数可以被解释为四个 8 位的字符。

C 联合体与结构体的区别

在 C 语言中,联合体和结构体都是用户自定义的数据类型,它们都可以包含多个不同类型的成员。但它们之间存在着本质的区别:

  • 内存分配:结构体的每个成员都拥有独立的内存空间,结构体变量的总大小是其所有成员大小之和(可能存在内存对齐)。而联合体的所有成员共享同一块内存空间,联合体变量的大小等于其最大的成员的大小。
  • 数据存储:在任何给定的时间,结构体变量可以存储其所有成员的值。而联合体变量在任何给定的时间只能存储其一个成员的值。如果给联合体的一个成员赋值,其他成员的值将会被覆盖。

上一篇: C 枚举

下一篇: C typedef

给站长反馈

绿叶网正在不断完善中,小伙伴们如果发现任何问题,还望多多给站长反馈,谢谢!

邮箱:lvyenet@vip.qq.com

「绿叶网」服务号
绿叶网服务号放大
关注服务号,微信也能看教程。
绿叶网服务号