首页 > 其他分享 >联合体(Union)

联合体(Union)

时间:2025-01-17 13:04:36浏览次数:3  
标签:字节 Union 成员 联合体 union 内存 printf

联合体(Union)简介

联合体(union)是 C 和 C++ 编程语言中的一种数据结构,和结构体(struct)类似,但有一些重要的区别。

定义
  • 联合体中的所有成员共享同一段内存,也就是说,联合体中的多个成员变量会占用相同的地址,但是在任何一个时间点只能存储一个成员的值。

1. 联合体的定义和语法

定义语法
union UnionName {
    DataType member1;
    DataType member2;
    ...
};
示例
union Example {
    int i;       // 整数,占用 4 字节
    float f;     // 浮点数,占用 4 字节
    char c;      // 字符,占用 1 字节
};
  • 这里的联合体 Example 包含了 3 个成员:
    • 一个整数 i,占用 4 字节。
    • 一个浮点数 f,占用 4 字节。
    • 一个字符 c,占用 1 字节。
  • 存储特点
    • 联合体的总大小取决于它的最大成员所需的内存大小(这里是 4 字节,因为 intfloat 都占 4 字节)。

2. 联合体的内存分配

内存共享特点
  • 联合体中的所有成员都共享同一块内存,因此:
    • 写入一个成员会覆盖其他成员的值。
    • 在任意时刻,联合体中只能存储一个有效值。
示例
union Example {
    int i;       // 整数,占用 4 字节
    float f;     // 浮点数,占用 4 字节
    char c[4];   // 字符数组,占用 4 字节
};
union Example ex;
ex.i = 42;      // 写入整数 42
printf("i: %d\n", ex.i);    // 输出 i 的值:42
ex.f = 3.14;    // 写入浮点数 3.14
printf("f: %.2f\n", ex.f);  // 输出 f 的值:3.14
printf("i: %d\n", ex.i);    // 输出 i 的值:此时 i 的值已被覆盖
输出
i: 42
f: 3.14
i: 1078523331   // i 的值被 f 的写入覆盖,解释为浮点数的二进制形式

3. 联合体的用途

3.1 内存节省
  • 联合体非常适合需要节省内存的场景。
  • 由于多个成员共享同一段内存,可以显著减少内存占用。
3.2 数据转换
  • 联合体常用于类型转换,允许以不同的方式访问同一块数据。
示例:浮点数与二进制表示的转换
#include <stdio.h>
union FloatToBits {
    float f;
    unsigned int bits;
};
int main() {
    union FloatToBits data;
    data.f = 3.14;   // 写入浮点数
    printf("Float: %.2f\n", data.f);          // 输出浮点数
    printf("Bits: 0x%X\n", data.bits);        // 输出二进制表示
    return 0;
}
输出
Float: 3.14
Bits: 0x4048F5C3
  • 同一块内存可以通过 data.f 访问为浮点数,通过 data.bits 访问为其二进制位。

4. 联合体的常见用途

4.1 数据协议处理
  • 联合体常用于解析二进制数据流。例如,在通讯协议中,可以通过联合体将字节流解析为特定的数据结构。
示例:解析 16 位数据的高低字节
union Data16 {
    unsigned short full;  // 16 位数据
    struct {
        unsigned char low;  // 低字节
        unsigned char high; // 高字节
    } parts;
};
int main() {
    union Data16 data;
    data.full = 0x1234; // 写入 16 位数据
    printf("Full: 0x%X\n", data.full);      // 输出完整值
    printf("High: 0x%X\n", data.parts.high); // 输出高字节
    printf("Low: 0x%X\n", data.parts.low);   // 输出低字节
    return 0;
}
输出
Full: 0x1234
High: 0x12
Low: 0x34
应用场景
  • 网络协议
    • 在网络通讯中,经常需要解析协议头部,例如 IP 包头、TCP 包头等,联合体可以方便地拆解字段。
  • 嵌入式开发
    • 在嵌入式系统中,用联合体将字节序列解析为多字节变量(如 intfloat)。

4.2 硬件寄存器操作
  • 联合体可以用于操作硬件寄存器,通过联合体直接访问寄存器的特定位。
示例:32 位寄存器的分段访问
union Register {
    unsigned int value;  // 寄存器的完整值
    struct {
        unsigned char byte0;  // 第 0 字节
        unsigned char byte1;  // 第 1 字节
        unsigned char byte2;  // 第 2 字节
        unsigned char byte3;  // 第 3 字节
    } bytes;
};
int main() {
    union Register reg;
    reg.value = 0x12345678; // 写入寄存器值
    printf("Byte 0: 0x%X\n", reg.bytes.byte0); // 输出低字节
    printf("Byte 1: 0x%X\n", reg.bytes.byte1); // 输出次低字节
    printf("Byte 2: 0x%X\n", reg.bytes.byte2); // 输出次高字节
    printf("Byte 3: 0x%X\n", reg.bytes.byte3); // 输出高字节
    return 0;
}
输出
Byte 0: 0x78
Byte 1: 0x56
Byte 2: 0x34
Byte 3: 0x12

5. 联合体与结构体的区别

特性联合体(union)结构体(struct)
内存分配所有成员共享同一段内存,大小由最大成员决定每个成员都有独立的内存,大小是所有成员内存之和
成员访问同一时刻只能存储一个成员,访问其他成员可能导致数据不一致所有成员可以同时访问,互不干扰
用途内存节省,数据转换,多种数据形式的联合表示表示多种属性的组合体
使用限制不适合需要同时使用多个成员的场景可以同时访问多个成员

6. 注意事项

  1. 数据覆盖
    • 由于所有成员共享内存,当你写入一个成员时,会覆盖其他成员的值。
    • 使用联合体时要非常小心,确保对成员的访问逻辑正确。
  2. 对齐与大小
    • 联合体的大小由其最大成员的大小决定,并可能受到编译器对齐(padding)的影响。
  3. 联合体与类型安全
    • 联合体没有类型检查机制,读写不同类型的成员时可能导致不安全行为。

7. 总结

  • 联合体是 C/C++ 中的一种高级数据类型,适用于节省内存、数据解析和类型转换等场景。
  • 其核心特点是成员共享同一段内存,这既带来了灵活性,也对程序员提出了更高的使用要求。
  • 常见用途包括:
    1. 数据协议解析(如解析高低字节)。
    2. 硬件寄存器操作
    3. 浮点数与二进制位的转换
    4. 节省内存空间的场景

如有侵权,联系删除

标签:字节,Union,成员,联合体,union,内存,printf
From: https://blog.csdn.net/Flocx/article/details/145205156

相关文章

  • sql的join,inner join,union,union all的区别
    JOIN和INNERJOIN:JOIN 是SQL中用于将两个或多个表中的数据根据指定的关联条件组合在一起的操作。INNERJOIN 是 JOIN 的一种,它返回两个表中满足关联条件的行。语法:收起sql SELECTcolumnsFROMtable1JOINtable2ONtable1.column=table2.column;......
  • 百度面试真题 - 大小端字节序问题(联合体/共用体 - 面试加分)
    标题大小端字节序标题大小端字节序(联合体/共用体)优质资源以上bilibili教程(大小端存储-详细简介)(空间也有)目录​编辑简介大小端存储(空间视频详解):强制类型转换- char*:巧用联合体,解决百度面试题 - 大小端字节序问题:使用联合体的优点:简介......
  • Linq中的设置操作 (C#):Distinct 和 DistinctBy、Except 和 ExceptBy、Intersect 和 In
    LINQ中的集运算是指根据相同或单独集合中是否存在等效元素来生成结果集的查询运算。注:这些示例使用System.Collections.Generic.IEnumerable<T>数据源。基于System.Linq.IQueryProvider的数据源使用System.Linq.IQueryable<T>数据源和表达式树。表达式树对允许的C#语......
  • 【Web安全】SQL 注入攻击技巧详解:UNION 注入(UNION SQL Injection)
    【Web安全】SQL注入攻击技巧详解:UNION注入(UNIONSQLInjection)引言UNION注入是一种利用SQL的UNION操作符进行注入攻击的技术。攻击者通过合并两个或多个SELECT语句的结果集,可以获取数据库中未授权的数据。这种注入技术要求攻击者对数据库的结构有一定的了解,尤其是列的数......
  • 《docker基础篇:4.Docker镜像》包括是什么、分层的镜像、UnionFS(联合文件系统)、docker
    @目录4.Docker镜像4.1是什么4.1.1是什么4.1.2分层的镜像4.1.3UnionFS(联合文件系统)4.1.4docker镜像的加载原理4.1.5为什么docker镜像要采用这种分层结构呢4.2重点理解4.3docker镜像commit操作案例本人其他相关文章链接4.Docker镜像这一块主要讲解docker镜像的底层原理。......
  • sql注入学习-union联合注入
     SQL注入(SQLInjection)是一种常见的网络攻击手段,攻击者通过在Web应用程序的输入字段中插入恶意SQL代码,欺骗后台数据库执行非授权的SQL语句。SQL注入可以用于获取、篡改或删除数据库中的数据,甚至可以用于执行系统命令,导致数据泄露、数据破坏或服务器被控制等严重后果......
  • `we_chat_open_id`, `we_chat_subscribe`, 和 `we_chat_union_id` 这三个字段的区别
    好的,我们来详细解释一下we_chat_open_id,we_chat_subscribe,和we_chat_union_id这三个字段的区别,它们都是与微信用户相关的标识符和信息:1.we_chat_open_id(varchar(255)DEFAULTNULL)定义:微信OpenID是微信公众平台为每个用户在特定公众号或小程序中生成的唯一......
  • 《 C++ 点滴漫谈: 十二 》让内存飞一会儿:C++ Union 的神奇魔法
    摘要C++中的union关键字是一种独特的内存共享机制,通过允许多个成员共享同一段内存,提供了高效的存储方式和灵活的操作手段。本博客深入探讨了union的基础概念、成员规则、构造函数与析构函数的使用,以及现代C++提供的新特性支持。同时,我们分析了union的典型应用场景......
  • WPF GeometryCombineMode Exclue,Intersect,Union,Xor
      <Windowx:Class="WpfApp72.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.micro......
  • C:结构体、联合体
    结构体结构体类型的存储区里包含多个子存储区,每个子存储区可以用来记录对应的信息子存储区(成员变量)可以是不同的数据类型,也可以是结构体类型的结构体声明语句用来创建结构体类型,需要使用struct关键字结构体类型名称由关键字struct和结构体名称一起构成结构体成员变量声......