c语言联合union 的联合变量,联合标记,联合类型定义的区别

本文详细介绍了C语言中联合体的基本概念与使用方法,通过具体的代码示例展示了联合体成员之间的内存分配及覆盖特性,有助于读者理解联合体的工作原理。
联合的特点:
像结构一样,联合也有多个成员,而且这些成员具有不同的数据类型
编译器职位联合中字大的成员非配足够的内存空间。
联合中的成员,同一时间只能有一个,彼此覆盖。


联合有点像电话亭,有一个人进去了,其他人只能等着,好像联合用刀的不会很多吧。


//
//  main.c
//  UnionTest
//
//  Created by 千 on 16/7/22.
//  Copyright © 2016年 kodulf. All rights reserved.
//

#include <stdio.h>

int main(int argc, const char * argv[]) {
    // insert code here...
    printf("Hello, World!\n");
    /*
     和结构一样:
     联合变量,联合标记,联合类型定义;
     联合变量,使用到就要申明很麻烦。
     联合标记,可以直接声明,但是前面要有union来修改
     联合类型定义,可以像java 一样定义
     */
    //联合的变量
    int i;
    union{
        int i;
        float f;
        char c;
    }u;
    //访问成员变量名臣,成员名称
    u.i=10;
    printf("u.i=%d\n",u.i);
    printf("--------\n");
    u.f=12.0f;
    printf("u.i=%d",u.i);//i已经被f覆盖了
    printf("u.f=%f\n",u.f);
    printf("--------\n");
    u.c='c';
    printf("u.i=%d",u.i);
    printf("u.f=%f",u.f);
    printf("u.c=%c\n",u.c);//c覆盖了上面的f
    printf("--------\n");
    /*
     输出结果:
     u.i=10
     --------
     u.i=1094713344u.f=12.000000
     --------
     u.i=1094713443u.f=12.000094u.c=c
     */
    
    //和之前的结构变量和结构类型标记的一样,如果不使用结构类型标记,那么每一次使用到新的结构变量的时候都要重新的创建。
    //联合的标示
    union MyUnion{
        int i;
        float f;
        char c;
    };
    
    union MyUnion mu,mu2;
    mu.i=10;
    printf("mu.i=%d\n",mu.i);
    printf("--------\n");
    mu.f=12.0f;
    printf("mu.i=%d",mu.i);//i已经被f覆盖了
    printf("mu.f=%f\n",mu.f);
    printf("--------\n");
    mu2.c='c';
    printf("mu2.c=%c\n",mu2.c);//
    
    
    //和结构类型定义一样,这里也有    联合的类型定义
    typedef union{
        int i;
        float f;
        char c;
    }MyUnionType;
    
    MyUnionType myU,myu2;
    myu.i=10;
    printf("myu.i=%d\n",myu.i);
    printf("--------\n");
    mu.f=12.0f;
    printf("myu.i=%d",myu.i);//i已经被f覆盖了
    printf("myu.f=%f\n",myu.f);
    printf("--------\n");
    mu2.c='c';
    printf("myu2.c=%c\n",myu2.c);//
    
    
    return 0;
}


<think>我们正在讨论C语言中的union关键字。根据引用内容,union联合体)是一种特殊的数据类型,它允许在同一个内存位置存储不同的数据类型,所有成员共享同一块内存空间。联合体的大小等于其最大成员的大小。 引用[1]提到:共用体可以让您在同一个内存位置存储不同类型的数据,从而节省空间和提高效率。 引用[2]提供了基本语法和示例:联合体的所有成员共享相同的内存区域,因此联合体的大小等于其最大成员的大小。 引用[3]强调:union维护足够的空间来存放多个数据成员中的“一种”,同一时间只能储存其中一个数据成员。 引用[4]则提到了联合体的初始化方法。 接下来,我将详细解释union定义和使用方法,包括: 1. 定义联合体 2. 初始化联合体 3. 访问联合体成员 4. 联合体的应用场景 5. 注意事项 同时,我会在适当的地方添加引用标记。</think>### C语言`union`关键字的定义与使用方法详解 `union`(联合体)是C语言中一种特殊的数据类型,允许在**同一块内存空间**存储不同类型的数据。所有成员共享相同的内存起始地址,联合体的大小由其**最大成员**决定。 --- #### 一、联合体的定义语法 ```c union 联合体名称 { 数据类型 成员1; 数据类型 成员2; // ... }; ``` - **内存共享**:所有成员占用同一内存区域(起始地址相同) - **空间计算**:联合体大小 = 最大成员的大小(需考虑内存对齐) - **示例定义**: ```c union Data { int i; // 4字节 float f; // 4字节 char str[20]; // 20字节 → 联合体总大小为20字节 }; ``` --- #### 二、联合体的使用方式 ##### 1. **声明与初始化** ```c // 声明联合变量 union Data data; // 初始化(C99标准支持) union Data data = {.i = 10}; // 指定初始化成员i union Data data = {10}; // 默认初始化第一个成员(i) ``` > 注意:未初始化的联合体成员值为未定义[^4] ##### 2. **成员赋值与访问** ```c data.i = 100; // 写入int类型值 printf("%d", data.i); // 读取int值 data.f = 3.14; // 覆盖原有值(i被覆盖) printf("%f", data.f); // 读取float值 strcpy(data.str, "Hello"); // 写入字符串 ``` ⚠️ **关键特性**: - 同一时刻**仅一个成员有效**(新赋值会覆盖旧值) - 访问非当前写入的成员可能导致**未定义行为**[^2] ##### 3. **内存布局演示** ```mermaid graph LR A[内存地址0x1000] --> B[int i] A --> C[float f] A --> D[char str[20]] ``` - 所有成员从`0x1000`开始存储 - 写入`i=0x11223344`后: ``` 地址: 0x1000 0x1001 0x1002 0x1003 数据: 0x44 0x33 0x22 0x11 ``` - 写入`f=3.14`将覆盖该区域 --- #### 三、联合体的应用场景 1. **节省内存空间** 处理互斥数据时(如协议解析): ```c union Packet { struct { int type; } header; struct { float value; } sensor; struct { char id[10]; } command; }; ``` 2. **类型转换** 安全实现二进制数据解释: ```c union Converter { float f; uint32_t bits; } conv; conv.f = 2.5; printf("IEEE754编码: 0x%08X", conv.bits); // 输出浮点数的二进制表示 ``` 3. **硬件寄存器映射** 访问同一寄存器的不同位域: ```c union StatusReg { uint32_t raw; struct { uint32_t ready:1; uint32_t error:1; uint32_t reserved:30; } flags; }; ``` --- #### 四、与结构体(`struct`)的关键区别 | 特性 | `union` | `struct` | |--------------|-----------------------------|------------------------| | **内存占用** | 等于最大成员大小 | 所有成员大小之和 | | **成员关系** | 互斥(同一时间仅一个有效) | 独立共存 | | **访问安全** | 访问非当前成员导致未定义行为 | 所有成员可安全访问 | | **应用场景** | 内存敏感场景/类型转换 | 数据聚合 | > 示例: > ```c > struct S { int a; float b; }; // 大小≥8字节 > union U { int a; float b; }; // 大小=4字节 > ``` --- #### 五、注意事项 1. **初始化限制** 只能初始化第一个成员(C89标准),C99支持指定成员初始化[^4] 2. **字节序问题** 多字节类型(如`int`)在不同平台可能有不同字节序: ```c union EndianTest { uint32_t num; uint8_t bytes[4]; } test = {0x12345678}; // 大端: bytes[0]=0x12, 小端: bytes[0]=0x78 ``` 3. **未定义行为风险** 访问未正确赋值的成员: ```c union U u; u.f = 1.0; printf("%d", u.i); // 结果不可预测! ``` > 联合体在嵌入式开发中应用广泛(如CAN通信协议解析),但需严格管理成员访问时序[^1][^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值