union struct c语言

99ANYc3cd6
预计阅读时长 18 分钟
位置: 首页 C语言 正文

struct (结构体)

核心思想:打包

结构体就像一个打包盒,你可以把不同类型、不同大小的变量(int, char, float)打包在一起,形成一个整体,这些变量在内存中是独立存放的,互不干扰。

union struct c语言
(图片来源网络,侵删)

内存布局

结构体的总大小是其所有成员大小之和(可能会有内存对齐填充)。

语法

struct 结构体名 {
    数据类型 成员1;
    数据类型 成员2;
    // ...
};
// 定义结构体变量
struct 结构体名 变量名;
// 或者
struct {
    数据类型 成员1;
    数据类型 成员2;
} 变量名; // 匿名结构体

代码示例

#include <stdio.h>
// 定义一个学生结构体
struct Student {
    int id;         // 4字节
    char name[50];  // 50字节
    float score;    // 4字节
};
int main() {
    // 声明一个结构体变量 s1
    struct Student s1;
    // 访问成员使用点运算符 .
    s1.id = 101;
    sprintf(s1.name, "Zhang San"); // 安全的字符串赋值方式
    s1.score = 95.5f;
    printf("Student ID: %d\n", s1.id);
    printf("Student Name: %s\n", s1.name);
    printf("Student Score: %.2f\n", s1.score);
    // 计算结构体大小
    printf("Size of struct Student: %zu bytes\n", sizeof(struct Student)); // 输出通常是 58 (4+50+4 + 对齐填充)
    return 0;
}

主要用途

  • 组织相关数据:将逻辑上相关的数据项组合成一个单元,一个学生的信息、一个汽车的配置等。
  • 函数参数:将多个相关参数作为一个结构体传递,比传递多个独立参数更清晰。
  • 返回值:函数可以返回一个包含多个值的结构体。

union (联合体)

核心思想:共享

联合体就像一个共享的储物格,但这个储物格的“形状”可以变化,它允许你在同一个内存地址上存储不同类型的数据,这些成员是共享同一块内存空间的。

内存布局

联合体的总大小是其最大成员的大小(同样可能有内存对齐填充),任何时候,只有一个成员的数据是有效的。

语法

union 联合体名 {
    数据类型 成员1;
    数据类型 成员2;
    // ...
};
// 定义联合体变量
union 联合体名 变量名;
// 或者
union {
    数据类型 成员1;
    数据类型 成员2;
} 变量名; // 匿名联合体

代码示例

#include <stdio.h>
// 定义一个数据联合体
union Data {
    int i;
    float f;
    char str[20];
};
int main() {
    // 声明一个联合体变量 data
    union Data data;
    // 访问成员同样使用点运算符 .
    // 注意:每次只能使用一个成员,赋值会覆盖其他成员的值
    data.i = 10;
    printf("data.i: %d\n", data.i);
    data.f = 220.5;
    printf("data.f: %f\n", data.f); // data.i 的值已经被破坏了
    printf("data.i (after f assignment): %d (garbage value)\n", data.i);
    // 你不能同时安全地使用 str 和 i 或 f
    // strcpy(data.str, "Hello C");
    // printf("data.str: %s\n", data.str);
    // printf("data.i (after str assignment): %d (garbage value)\n", data.i);
    // 计算联合体大小
    printf("Size of union Data: %zu bytes\n", sizeof(union Data)); // 输出通常是 20 (str[20]是最大的)
    return 0;
}

主要用途

  • 节省内存:当你有一组数据,但在任何时刻只会使用其中一个时,使用联合体可以大大节省内存,一个变量可能是整数也可能是浮点数,但你不会同时需要它的两种表示。
  • 类型双关:允许以不同的数据类型解释同一块内存,这在底层编程、硬件交互或网络协议解析中非常常见。
  • 构建“变体”类型:可以和 struct 结合,创建一个可以存储不同类型数据的结构,一个 struct 有一个 type 字段和一个 union 字段,union 中根据 type 的值来决定使用哪个成员。

struct vs union 核心区别总结

特性 struct (结构体) union (联合体)
核心思想 打包 共享
内存布局 所有成员在内存中连续、独立存放,所有成员同时存在且有效。 所有成员共享同一块内存空间,任何时刻只有一个成员的值是有效的。
总大小 所有成员大小之和(考虑内存对齐)。 最大成员的大小(考虑内存对齐)。
成员访问 可以同时访问所有成员,互不影响。 一次只能访问一个成员,对某个成员赋值会覆盖其他成员的值。
主要用途 组织和管理相关的、需要共存的数据。 节省内存;实现类型双关;处理多种可能的数据格式。

经典应用场景:struct + union

这是联合体最强大的用法之一,常用于实现“变体对象”(Variant Object)或标记联合(Tagged Union)。

union struct c语言
(图片来源网络,侵删)

假设我们要设计一个可以表示不同类型几何图形的数据结构,一个图形可以是圆形、矩形或三角形,但它们的数据不同。

#include <stdio.h>
#include <string.h>
// 定义联合体,用于存放不同图形的数据
union ShapeData {
    // 圆形: 只需要半径
    struct {
        float radius;
    } circle;
    // 矩形: 需要长和宽
    struct {
        float length;
        float width;
    } rectangle;
    // 三角形: 需要底和高
    struct {
        float base;
        float height;
    } triangle;
};
// 定义枚举,标记当前图形的类型
enum ShapeType {
    SHAPE_CIRCLE,
    SHAPE_RECTANGLE,
    SHAPE_TRIANGLE
};
// 定义主结构体,包含类型标记和共享数据
struct Shape {
    enum ShapeType type; // 标记位
    union ShapeData data; // 共享的数据
};
// 计算面积的函数
float calculateArea(struct Shape* s) {
    switch (s->type) {
        case SHAPE_CIRCLE:
            return 3.14159f * s->data.circle.radius * s->data.circle.radius;
        case SHAPE_RECTANGLE:
            return s->data.rectangle.length * s->data.rectangle.width;
        case SHAPE_TRIANGLE:
            return 0.5f * s->data.triangle.base * s->data.triangle.height;
        default:
            return 0.0f;
    }
}
int main() {
    // 创建一个圆形
    struct Shape myCircle;
    myCircle.type = SHAPE_CIRCLE;
    myCircle.data.circle.radius = 10.0f;
    printf("Circle Area: %.2f\n", calculateArea(&myCircle));
    // 创建一个矩形
    struct Shape myRectangle;
    myRectangle.type = SHAPE_RECTANGLE;
    myRectangle.data.rectangle.length = 5.0f;
    myRectangle.data.rectangle.width = 8.0f;
    printf("Rectangle Area: %.2f\n", calculateArea(&myRectangle));
    // 错误示范:如果误用类型,后果严重
    // myCircle.type = SHAPE_CIRCLE;
    // printf("Rectangle's radius: %.2f\n", myCircle.data.circle.radius); // 这是无意义的,因为myCircle.data里存的是rectangle的数据
    return 0;
}

在这个例子中:

  • struct Shape 是外层容器,它知道当前存储的是哪种图形(type)。
  • union ShapeData 是真正的“变体”部分,它根据 type 的值来决定如何解读其内部的数据。
  • 这种模式非常安全且高效,避免了使用 void* 指针带来的风险。
  • struct 当你想把几个东西放在一起,并且同时需要使用它们。
  • union 当你有几个东西,但同一时间只用其中一个,想节省空间或者想用不同方式看待同一块内存

理解这两者的根本区别——内存是独立打包还是共享——是掌握 C 语言数据类型的关键一步。

-- 展开阅读全文 --
头像
dede list diy数据表
« 上一篇 2025-12-23
织梦list如何通过typeid调用指定栏目?
下一篇 » 2025-12-23

相关文章

取消
微信二维码
支付宝二维码

目录[+]