联合体 (Union) - “多功能存储盒”
核心概念
联合体是一种特殊的数据类型,允许在相同的内存位置存储不同的数据类型。所有成员共享同一块内存空间。
内存模型演示
内存地址: 0x1000 0x1001 0x1002 0x1003 0x1004 0x1005 0x1006 0x1007
┌───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┐
使用 int: │ 字节0 │ 字节1 │ 字节2 │ 字节3 │ │ │ │ │
└───────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┘
┌───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┐
使用 double: │ 字节0 │ 字节1 │ 字节2 │ 字节3 │ 字节4 │ 字节5 │ 字节6 │ 字节7 │
└───────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┘
基本特征
- 内存共享:所有成员共用同一内存块
- 尺寸最大:联合体大小 = 最大成员的大小 + 内存对齐
- 互斥访问:同一时刻只有一个成员有效
- 覆盖效应:赋值新成员会覆盖旧成员的值
定义与声明
// 外部定义联合体类型 DataBox(全局可见)
union DataBox {
int number; // 整型成员
char letter; // 字符型成员
double value; // 双精度浮点型成员
char text[20]; // 字符数组成员
};
int main() {
// 声明外部定义的 DataBox 类型变量
union DataBox box;
// 可以对 box 赋值(示例)
box.number = 100; // 赋值整型成员
printf("box.number = %d\n", box.number);
// 若需要在 main 内定义新的联合体,需使用不同的类型名(避免冲突)
union DataBoxInner { // 新类型名:DataBoxInner(与外部 DataBox 不重复)
int num; // 新联合体的整型成员
char ch; // 新联合体的字符成员
} box1, box2; // 声明新类型的变量 box1、box2
// 对新联合体变量赋值(示例)
box1.ch = 'A'; // 给 box1 的字符成员赋值
printf("box1.ch = %c\n", box1.ch);
box2.num = 200; // 给 box2 的整型成员赋值
printf("box2.num = %d\n", box2.num);
return 0;
}
操作示例
联合体成员共用同一块内存,但数据有效性取决于赋值操作:未赋值时,内存中是随机数据,任何成员解读都无意义(状态未定义);只有最后一次被赋值的成员,因其数据是按自身类型写入的,才能正确解读内存内容,成为可安全访问的有效成员。
#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 : %.2f\n", data.f);
// 使用字符串成员(会覆盖浮点数)
strcpy(data.str, "C Programming");
printf("data.str : %s\n", data.str);
return 0;
}
联合体的高级用法:标签联合体 (Tagged Union)
概念
标签联合体 = 类型标签 + 联合体,用于安全地处理多种数据类型。
// 定义数据类型标签
#define TYPE_INT 1
#define TYPE_FLOAT 2
#define TYPE_STRING 3// 标签联合体结构
struct TaggedData {
int type_tag;// 类型标签,指示当前有效的数据类型
union {
int int_data;// 整型数据
float float_data;// 浮点数据
char string_data[50];// 字符串数据
} value;// 联合体存储实际数据
};
完整示例
#include <stdio.h>
#include <string.h>
#define TYPE_INT 1
#define TYPE_FLOAT 2
#define TYPE_STRING 3
struct Variant{
int type;
union {
int i;
float f;
char s[20];
} data;
};
void printVariant(struct Variant v) {
switch(v.type) {
case TYPE_INT:
printf("Integer: %d\n", v.data.i);
break;
case TYPE_FLOAT:
printf("Float: %.2f\n", v.data.f);
break;
case TYPE_STRING:
printf("String: %s\n", v.data.s);
break;
default:
printf("Unknown type\n");
}
}
int main() {
struct Variant var;
// 存储整数
var.type = TYPE_INT;
var.data.i = 100;
printVariant(var);
// 存储浮点数
var.type = TYPE_FLOAT;
var.data.f = 3.14;
printVariant(var);
// 存储字符串
var.type = TYPE_STRING;
strcpy(var.data.s, "Hello Union");
printVariant(var);
return 0;
}
枚举 (Enum) - “有名字的数字”
基本概念
枚举为整数值提供有意义的名称,提高代码可读性和可维护性。
定义与使用
// 定义枚举类型
enum Weekday {
MONDAY,// 默认为0
TUESDAY,// 自动加1
WEDNESDAY,// 2
THURSDAY,// 3
FRIDAY,// 4
SATURDAY,// 5
SUNDAY// 6
};
// 自定义枚举值
enum Status {
OFF = 0,
ON = 1,
STANDBY = 2
};
// 部分自定义
enum Color {
RED,// 0
GREEN = 5,//如果赋值,下一个元素的值会从当前值累加
BLUE,// 6
YELLOW = 10
};
枚举变量操作
// 匿名枚举 + typedef 一步定义类型别名
typedef enum { RED, YELLOW, GREEN } TrafficLight;
int main() {
TrafficLight light = GREEN; // 直接用简化后的类型名声明变量
switch(light) {
case RED:
printf("Stop!\n");
break;
case YELLOW:
printf("Caution!\n");
break;
case GREEN:
printf("Go!\n");
break;
default:
break;
}
printf("RED = %d, GREEN = %d\n", RED, GREEN);
return 0;
}
核心思想:联合体用于数据存储的多样性,枚举用于代码逻辑的清晰性。
1954

被折叠的 条评论
为什么被折叠?



