C语言基础系列【15】union 共用体

news/2025/2/22 2:07:41

博主介绍:程序喵大人

  • 35- 资深C/C++/Rust/Android/iOS客户端开发
  • 10年大厂工作经验
  • 嵌入式/人工智能/自动驾驶/音视频/游戏开发入门级选手
  • 《C++20高级编程》《C++23高级编程》等多本书籍著译者
  • 更多原创精品文章,首发gzh,见文末
  • 👇👇记得订阅专栏,以防走丢👇👇
    😃C++基础系列专栏
    😃C语言基础系列

union是一种特殊的数据结构,union在相同的内存位置存储不同类型的数据。union中的所有成员共享同一块内存空间,因此在任何时候,union只能存储其成员中的一个值。

示例代码

#include <iostream>

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

int main() {
    Data data;

    // 存储整数
    data.i = 42;
    std::cout << "Integer: " << data.i << std::endl;

    // 存储浮点数(注意:会覆盖之前的整数数据)
    data.f = 3.14f;
    std::cout << "Float: " << data.f << std::endl;

    // 存储字符串(注意:会覆盖之前的浮点数数据)
    strcpy(data.str, "Hello, Union!");
    std::cout << "String: " << data.str << std::endl;

    return 0;
}

在这个示例中,我们定义了一个Data union,它包含三个成员:

  • i(整型)
  • f(浮点型)
  • str(字符数组)

然后演示了如何向union中存储不同类型的数据。

请注意,由于union的所有成员共享内存,因此同时访问多个成员可能会导致未定义行为。下面详细介绍。

共用体的定义与基本用法

共用体的定义方式与结构体类似,但使用union关键字。

共用体可以包含多个成员,但任何时候只能有一个成员带有有效值。

因为共用体的所有成员共享同一块内存区域,当给某个成员赋值时,会覆盖该内存区域中之前存储的数据。

定义共用体的语法如下

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

其中,共用体名是可选的,用于标识该共用体类型。成员类型成员名则定义了共用体中包含的成员及其类型。

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

这个例子,定义了一个名为Data的共用体,它包含三个成员:一个整型变量i,一个浮点型变量f,以及一个字符数组str

使用共用体

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

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

int main() {
    union Data data;

    // 给整型成员赋值
    data.i = 10;
    printf("data.i: %d\n", data.i);

    // 给浮点型成员赋值(会覆盖之前的整数值)
    data.f = 220.5;
    printf("data.f: %.5f\n", data.f);

    // 给字符数组成员赋值(会覆盖之前的浮点数值)
    strcpy(data.str, "Hello, Union!");
    printf("data.str: %s\n", data.str);

    return 0;
}

在这个示例中,我们定义了一个Data类型的共用体变量data,并分别给它的整型、浮点型和字符数组成员赋值。由于共用体的成员共享同一块内存,因此每次赋值都会覆盖之前存储的数据。

共用体的内存占用

共用体占用的内存大小等于其最大成员所占用的内存大小。

因为共用体的所有成员都存储在同一个内存位置,所以只需要足够的空间来存储最大的成员即可。

示例

#include <stdio.h>

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

int main() {
    printf("Size of union Data: %zu bytes\n", sizeof(union Data));
    return 0;
}

在这个示例中,我们打印了Data类型共用体的内存大小。由于字符数组str是成员中占用空间最大的(20个字节),因此Data类型共用体的内存大小也是20个字节。

共用体的应用场景

共用体在C语言中有多种应用场景:

  1. 节省内存
    当需要在同一个内存位置存储多种类型的数据时,可以使用共用体来节省内存。
    例如,在处理网络通信数据时,可能会根据协议的不同而需要解析不同类型的数据(如整型、浮点型、字符串等),此时可以使用共用体来存储这些数据。

  2. 类型转换
    共用体可以用于在不同类型之间进行转换。例如,在某些情况下,可能需要将一个整型数转换为浮点型数,或者将一个字符数组转换为整型数进行运算。虽然C语言提供了类型转换运算符,但在某些情况下使用共用体可能方便。

共用体与结构体的区别

  • 内存占用:结构体中的每个成员都占用独立的内存空间,而共用体中的所有成员共享同一块内存空间。
  • 数据访问:在结构体中,可以同时访问多个成员的值;而在共用体中,每次只能访问一个有效成员的值(即最后一次被赋值的成员)。
  • 用途:结构体通常用于表示具有固定结构和属性的数据记录(如学生信息、图书信息等),而共用体则更多地用于在不同类型的数据之间进行转换或节省内存。

共用体与结构体的结合使用

下面展示了如何将共用体与结构体结合使用来存储多种类型的数据和额外的属性信息:

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

// 定义一个共用体来存储不同类型的数据
union DataValue {
int intValue;
float floatValue;
char strValue[20];
};

// 定义一个结构体来存储数据值和额外的属性信息
struct DataRecord {
union DataValue value;
char type; // 用于标识存储的数据类型(如'i'表示整型,'f'表示浮点型,'s'表示字符串)
char description[50]; // 用于存储数据的描述信息
};

int main() {
    struct DataRecord record;

    // 存储整型数据
    record.value.intValue = 123;
    record.type = 'i';
    strcpy(record.description, "This is an integer value.");
    printf("Record 1: Type = %c, Value = %d, Description = %s\n", record.type, record.value.intValue, record.description);

    // 存储浮点型数据(会覆盖之前的整数值)
    record.value.floatValue = 456.78;
    record.type = 'f';
    strcpy(record.description, "This is a float value.");
    printf("Record 2: Type = %c, Value = %.2f, Description = %s\n", record.type, record.value.floatValue, record.description);

    // 存储字符串数据(会覆盖之前的浮点数值)
    strcpy(record.value.strValue, "Hello, Union!");
    record.type = 's';
    strcpy(record.description, "This is a string value.");
    printf("Record 3: Type = %c, Value = %s, Description = %s\n", record.type, record.value.strValue, record.description);

    return 0;
}

在这个示例中,我们定义了一个DataValue类型的共用体来存储不同类型的数据(整型、浮点型、字符串),又定义了一个DataRecord类型的结构体来存储数据值和额外的属性信息(如数据类型和描述信息)。

练习

  • 定义一个union,包含intfloatchar类型的成员。编写一个程序,允许用户选择数据类型(通过输入),然后根据选择输入相应的值,并输出该值。

码字不易,欢迎大家点赞关注评论,谢谢!


C++训练营

专为校招、社招3年工作经验的同学打造的1V1 C++训练营,量身定制学习计划、每日代码review,简历优化,面试辅导,已帮助多名学员获得offer!训练营介绍


http://www.niftyadmin.cn/n/5861518.html

相关文章

前端PDF转图片技术调研实战指南:从踩坑到高可用方案的深度解析

本文以真实业务场景为背景&#xff0c;深入剖析前端PDF转图片的 7大核心指标 &#xff0c;通过3000字详解5种方案对比性能压测数据&#xff0c;输出可复用的技术调研方法论。 一、技术调研认知误区与破局之道 1.1 需求理解典型翻车现场 // 错误案例&#xff1a;未明确需求边界…

【系统架构设计师】需求工程

目录 1. 说明2. 软件需求3. 需求阶段4. 需求管理5. 例题5.1 例题1 1. 说明 1.软件需求目前并没有统一的定义&#xff0c;但都包含以下几方面的内容。2.用户解决问题或达到目标所需条件或权能&#xff08;Capability&#xff09;。系统或系统部件要满足合同、标准、规范或其他正…

2月17日c语言框架

C语言框架以及常用函数 1&#xff0c;scanf&#xff08;&#xff09; 2&#xff0c;printf&#xff08;&#xff09; 1scanf&#xff08;&#xff09;函数的特点&#xff0c;必须填写参数&#xff0c;不然一定会报错 2输入一个整数&#xff0c;按回车之后&#xff0c;会出…

alt+tab切换导致linux桌面卡死的急救方案

环境 debian12 gnome43.9 解决办法 观察状态栏&#xff0c;其实系统是没有完全死机的&#xff0c;而且gnome也可能没有完全死机。 1. alt f4 关闭桌面上的程序&#xff0c;因为这个方案是我刚刚看到的&#xff0c;所以不确定能不能用&#xff0c;比起重启系统&#xff0c;…

嵌入式 Linux:使用设备树驱动GPIO全流程

文章目录 前言 一、设备树配置 1.1 添加 pinctrl 节点 1.2 添加 LED 设备节点 二、编写驱动程序 2.1 驱动程序框架 2.2 编译驱动程序 三、测试 总结 前言 在嵌入式 Linux 开发中&#xff0c;设备树&#xff08;Device Tree&#xff09;和 GPIO 子系统是控制硬件设备的重要工具…

多人协同开发 —— Git Aoneflow工作流

一、Aoneflow工作流核心架构 #mermaid-svg-rwTOe9qYwzG3wkdy {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-rwTOe9qYwzG3wkdy .error-icon{fill:#552222;}#mermaid-svg-rwTOe9qYwzG3wkdy .error-text{fill:#552222…

LeetCode热题100——滑动窗口/子串

文章目录 1. 无重复字符的最长子串1.1 题目链接1.2 题目描述1.3 解题代码1.4 解题思路 2. 找到字符串中所有字母异位词2.1 题目链接2.2 题目描述2.3 解题代码2.4 解题思路 3、和为 K 的子数组3.1 题目链接3.2 题目描述3.3 解题代码3.4 解题思路 4. 滑动窗口最大值4.1 题目链接4…

【学习笔记】Cadence电子设计全流程(二)原理图库的创建与设计(8-15)

【学习笔记】Cadence电子设计全流程&#xff08;二&#xff09;原理图库的创建与设计&#xff08;下&#xff09; 2.8 Cadence 软件自带元件库2.9 原理图元器件关联PCB2.10 原理图元器件库的移植2.11 已有原理图输出元器件库2.12 原理图设计中调用元器件库2.13 原理图元器件库关…