当前位置: 首页 > news >正文

初识C语言13.自定义类型(联合体与枚举)

目录

前言:

一、联合体(Union):共享内存的“多面手”

1.1 联合体的声明

1.2 联合体的核心特点:内存共享

1.3 联合体大小的计算

1.4 联合体的实际应用

二、枚举(Enum):给常量起“名字”

2.1 枚举类型的声明

2.2 枚举的核心优点

2.3枚举的实际使用

三、联合体与结构体的对比

总结


前言:

在C语言的自定义类型中,联合体(Union) 和 枚举(Enum) 是两种灵活且实用的工具,它们既能优化内存使用,也能让代码更具可读性。下面我们逐一解析这两种类型的核心知识

一、联合体(Union):共享内存的“多面手”

1.1 联合体的声明

像结构体⼀样,联合体也是由⼀个或者多个成员构成,这些成员可以不同的类型。

但是编译器只为最大的成员分配足够的内存空间。联合体的特点是所有成员共用同⼀块内存空间。所以联合体也叫:共用体。

给联合体其中⼀个成员赋值,其他成员的值也跟着变化。

// 联合体的声明
union MyUnion {char c;      // 成员1:字符型int i;       // 成员2:整型float f;     // 成员3:浮点型
};

- 关键字是  union ,后接联合体名(如  MyUnion ),大括号内是成员列表。
- 定义变量时,可直接在声明后加变量名: union MyUnion u1; ,也可通过 typedef 简化:

typedef union MyUnion {char c;int i;
} MyUnion;
MyUnion u2;  // 直接用MyUnion定义变量

1.2 联合体的核心特点:内存共享

与结构体(成员各自占用独立内存)不同,联合体的所有成员共享同一块内存空间,这是它最关键的特性:
 
- 同一时间,只能使用其中一个成员(若修改一个成员,其他成员的值会被覆盖)。
- 联合体的内存大小,由最大的成员大小决定(同时需满足内存对齐规则,见下文“大小计算”)。

//代码1
#include <stdio.h>
//联合类型的声明
union Un
{
char c;
int i;
};
int main()
{
//联合变量的定义
union Un un = {0};
// 下⾯输出的结果是⼀样的吗?
printf("%p\n", &(un.i));
printf("%p\n", &(un.c));
printf("%p\n", &un);
return 0;
}

输出结果:

001AF85C
001AF85C
001AF85C
//代码2
#include <stdio.h>
//联合类型的声明
union Un
{
char c;
int i;
};
int main()
{
//联合变量的定义
union Un un = {0};
un.i = 0x11223344;
un.c = 0x55;
printf("%x\n", un.i);
return 0;
}

输出结果:

11223355

代码1输出的三个地址⼀模⼀样,代码2的输出,我们发现将i的第4个字节的内容修改为55了。 我们仔细分析就可以画出,un的内存布局图。

1.3 联合体大小的计算

 
联合体的大小需满足两个规则:
 
1. 至少容纳最大的成员:大小 ≥ 最大成员的字节数;
2. 满足内存对齐:大小是“联合体中最大基本类型成员的对齐数”的整数倍。

union SizeDemo {char arr[5];  // 大小5字节(基本类型是char,对齐数1)int num;      // 大小4字节(基本类型是int,对齐数4)
};

- 最大成员是 arr[5] (5字节);
- 最大基本类型对齐数是 int 的4字节;
- 因此联合体大小需是4的整数倍,且≥5 → 最终大小是8字节。

1.4 联合体的实际应用

联合体的核心价值是节省内存,常见场景:
 
- 存储不同类型但互斥的数据:比如一个变量“要么是字符,要么是整数”,用联合体可避免额外内存开销;
- 类型转换(谨慎使用):利用内存共享特性,可实现不同类型的“强制转换”(但需注意平台的字节序):

union Convert {int i;char c[4];
};
union Convert u;
u.i = 0x12345678;
// 在小端序系统中,c[0]是0x78,c[1]是0x56,以此类推

二、枚举(Enum):给常量起“名字”

2.1 枚举类型的声明

枚举顾名思义就是⼀⼀列举。把可能的取值⼀⼀列举。

比如我们现实生活中:

⼀周的星期⼀到星期日是有限的7天,可以⼀⼀列举 性别有:男、女、保密,也可以⼀⼀列举

月份有12个有月,也可以⼀⼀列举 三原色,也是可以意义列举

这些数据的表⽰就可以使⽤枚举了

enum Day//星期
{
Mon,
Tues,
Wed,
Thur,
Fri,
Sat,
Sun
}


枚举是一种将一组常量命名的自定义类型,关键字是 enum ,用于替代无意义的数字常量

// 枚举的声明:表示“星期”的常量
enum Week {Mon,    // 默认值0Tue,    // 默认值1Wed,    // 默认值2Thu,    // 默认值3Fri,    // 默认值4Sat,    // 默认值5Sun     // 默认值6
};

- 大括号内是“枚举常量”(如 Mon 、 Tue ),默认从 0 开始依次递增;
- 也可手动指定枚举常量的值:

enum Week {Mon = 1,  // Mon=1Tue,      // Tue=2(自动递增)Wed = 5,  // Wed=5Thu       // Thu=6(自动递增)
};

2.2 枚举的核心优点

为什么使用枚举?

我们可以使用 #define 定义常量,为什么非要使用枚举?

枚举的优点:

1. 增加代码的可读性和可维护性

2. 和#define定义的标识符比较枚举有类型检查,更加严谨。

3. 便于调试,预处理阶段会删除 #define 定义的符号

4. 使用方便,⼀次可以定义多个常量

5. 枚举常量是遵循作用域规则的,枚举声明在函数内,只能在函数内使用

6. 简化维护:若需修改常量值,只需改枚举声明,无需逐个修改代码中的数字。

2.3枚举的实际使用

定义枚举变量后,可直接赋值枚举常量:

enum Week today;
today = Wed;  // 合法:赋值枚举常量
// today = 10;  // 不推荐:部分编译器会警告(类型不匹配)

也可通过 typedef 简化类型名:

typedef enum Week {Mon, Tue, Wed
} Week;
Week tomorrow = Tue;

三、联合体与结构体的对比

为了更清晰区分,我们用表格对比联合体和结构体:
 
特性 联合体(Union) 结构体(Struct) 
内存分配 所有成员共享同一块内存 每个成员占用独立内存,总大小是成员之和(+对齐) 
成员使用 同一时间只能用一个成员 可同时使用所有成员 
大小计算 由最大成员决定(+对齐) 成员大小之和(+对齐) 
典型场景 互斥数据的存储、节省内存 不同属性的组合存储(如“学生”的姓名、年龄) 

总结


联合体和枚举是C语言中“轻量级”的自定义类型:
 
- 联合体通过内存共享实现了内存优化,适合存储互斥的数据;
- 枚举通过给常量命名提升了代码的可读性与可维护性。
 
合理使用这两种类型,能让C语言代码更高效、更易读。

http://www.dtcms.com/a/519787.html

相关文章:

  • WebRTC入门指南:实时通信零基础
  • 深圳外贸营销型网站建设引擎搜索网站
  • Django 表单验证详解Form
  • k8s相关学习
  • 【2026计算机毕业设计】基于Django的社区婴幼儿预防接种系统
  • D030知识图谱科研文献论文推荐系统vue+django+Neo4j的知识图谱|论文本文相似度推荐|协同过滤
  • pg库、MySQL库和sqlite3基本操作
  • Android Studio新手开发第三十天
  • 住房建设部官方网站公示公告手机网站内容模块
  • 网站建设 数据库连接网站建设公司软件开
  • 深入理解栈与队列:核心特性与实战应用
  • 如何建一个免费的网站南昌做网站优化哪家好
  • 机器学习概念,算法原理及应用
  • Pytorch常用层总结
  • 【Deepseek OCR】重磅测试,mac环境下的体验【本人已经本地实验成功】
  • 轻量化(Lightweight)概念
  • [人工智能-大模型-58]:模型层技术 - 深度神经网络的本质是一个复杂的复合数学函数
  • 【小白笔记】将十进制数(Decimal)转换为二进制数(Binary),并计算二进制表示中“1”的个数
  • 长春怎么注册网站平台wordpress 视频列表
  • 【ReAcTable】面向表格问答任务的ReAct增强框架
  • Docker 部署 Elasticsearch 全流程手册
  • React 集成Redux数据状态管理 数据共享 全局共享
  • Docker与Nginx:现代Web部署的完美二重奏
  • 【JUnit实战3_08】第四章:从 JUnit 4 迁移到 JUnit 5
  • React 03
  • 前端基础之《React(2)—webpack简介-使用Babel》
  • 广州网站建设公司嘉御建设手机银行网站
  • 【Linux系统编程】软件包管理器
  • 怎么快速定位bug?如何编写测试用例?
  • NetIP,一款开源的快速网络信息查看工具