C语言联合体:内存共享的妙用

联合体

联合体(Union)是C语言中一种特殊的用户自定义数据类型,它允许在同一内存位置存储不同的数据类型。与结构体不同,联合体的所有成员共享同一块内存空间,这意味着任何时候只能使用联合体的一个成员。

结构体(struct)中的每个成员都有自己的内存空间,而联合体(union)的所有成员共享同一块内存空间。这是两者最本质的区别。

cpp 复制代码
// 结构体示例
struct Example {
    int i;     // 4字节
    float f;   // 4字节
    char c;    // 1字节
}; // 总大小约为12字节(考虑内存对齐)

// 联合体示例
union Example {
    int i;     // 4字节
    float f;   // 4字节
    char c;    // 1字节
}; // 总大小为4字节(最大成员的大小)

联合体的大小等于其最大成员的大小 (可能会因内存对齐而增加)。所有成员的起始地址都相同,它们相互覆盖。

cpp 复制代码
union 联合体标签名 {
    成员类型1 成员名1;
    成员类型2 成员名2;
    // ...更多成员
};

声明

cpp 复制代码
union Data data;  // 声明一个Data类型的联合体变量

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

初始化

cpp 复制代码
union Data data = {10};  // 初始化第一个成员i为10

union Data data = {.f = 3.14};  // 初始化成员f为3.14

联合体成员的访问

使用点运算符访问
cpp 复制代码
#include <stdio.h>
#include <string.h>

int main() {
    union Data {
        int i;
        float f;
        char str[20];
    };
    
    union Data data;
    
    // 给联合体成员赋值
    data.i = 10;
    printf("data.i: %d\n", data.i);
    
    // 给另一个成员赋值(会覆盖之前的值)
    data.f = 220.5;
    printf("data.f: %.1f\n", data.f);
    // 此时data.i的值已经被覆盖,不再是10
    printf("data.i: %d\n", data.i);  // 输出一个"奇怪"的值
    
    // 给字符数组成员赋值
    strcpy(data.str, "C语言");
    printf("data.str: %s\n", data.str);
    // 此时data.i和data.f的值都被覆盖
    
    return 0;
}
使用指针访问
cpp 复制代码
#include <stdio.h>

int main() {
    union Data {
        int i;
        float f;
        char str[20];
    };
    
    union Data data;
    union Data *ptr = &data;  // 定义联合体指针并指向data
    
    // 通过指针给联合体成员赋值
    ptr->i = 10;
    printf("ptr->i: %d\n", ptr->i);
    
    // 通过指针给另一个成员赋值
    ptr->f = 220.5;
    printf("ptr->f: %.1f\n", ptr->f);
    
    return 0;
}

联合体内存访问

cpp 复制代码
#include <stdio.h>

int main() {
    union Example {
        char c;     // 1字节
        short s;    // 2字节
        int i;      // 4字节
        double d;   // 8字节
    };
    
    union Example ex;
    
    printf("联合体大小: %lu字节\n", sizeof(union Example));  // 通常输出8
    
    printf("c的地址: %p\n", &ex.c);
    printf("s的地址: %p\n", &ex.s);
    printf("i的地址: %p\n", &ex.i);
    printf("d的地址: %p\n", &ex.d);
    // 所有成员的地址都相同
    
    return 0;
}

注意:

使用联合体时,最重要的是要记住任何时候只有一个成员的值是有效的。给一个成员赋值会覆盖其他成员的值。

cpp 复制代码
union Data {
    int i;
    float f;
};

union Data data;
data.i = 10;
data.f = 3.14;  // 此时data.i的值被覆盖,不再是10
cpp 复制代码
union {
    int i;
    float f;
} data;

data.i = 123456;
printf("%f\n", data.f);  // 类型不同,不安全。输出一个"奇怪"的浮点数
相关推荐
dialect_7 小时前
KMP算法
开发语言·c++·算法
reikocao7 小时前
卡尔曼滤波的动态机制:P如何改变融合权重
算法
漂流瓶jz8 小时前
UVA-1612 猜名次 题解答案代码 算法竞赛入门经典第二版
数据结构·算法·题解·排序·aoapc·算法竞赛入门经典
吞下星星的少年·-·8 小时前
Div.2 CF 1130B题(构造,贪心)
算法·贪心·构造
是main不是漫10 小时前
【双指针——移动零】数组划分类题目的入门基石
c++·算法
深圳市快瞳科技有限公司11 小时前
野外鸟类AI识别落地实录:输入适配、结构化输出、去重聚合与置信度分流的工程实践
算法·计算机视觉·鸟类识别·鸟类ai识别·野外鸟类观测·林业调查
专注仿真12 小时前
梯度提升类(XFBoost)算法详解与代码实例
开发语言·人工智能·python·算法·大模型训练·控制算法
小豆庄12 小时前
视频遮罩追踪退场后ID撞号的排查—多目标场景下的失效
opencv·算法·bug·视频·python3.11
Tisfy13 小时前
LeetCode 3882.网格图中最小异或路径:动态规划
算法·leetcode·动态规划
D e re k ZH14 小时前
P5025 [SNOI2017] 炸弹
c++·算法