自定义类型进阶:联合与枚举

个人主页流年如梦

专栏《C语言》

文章目录

本篇文章将学习联合体(共用体)、枚举类型,包含声明语法、特点、大小计算、使用场景、优点与实战等,全程高能,不容错过!!!

前言

在C语言的自定义类型体系中,结构体用于多成员独立封装、共存使用,联合体用于多成员共享同一块内存、互斥使用,枚举则用于将一组固定取值一一列举、规范常量定义。三者分别面向"组合""复用""命名"三大场景,是构建复杂程序、优化内存、提升代码可读性的必备工具。本篇文章将带领大家从基础语法、底层原理、实战用途等多方面学习探讨,帮助大家能够熟练掌握联合与枚举

一.联合体(共用体)

联合体也叫共用体 ,关键字为 union

联合体和结构体一样可以包含多个不同类型成员,但所有成员共用同一块内存空间,同一时间只能有效使用一个成员。

1.1联合体类型的声明

举个例子:

c 复制代码
union Un
{
	char c;
	int i;
};

🧐分析 :要用 union 定义联合类型;联合体成员可以是任意合法数据类型;所有成员共用起始地址,内存重叠

1.2如何使用联合体

举例(计算联合体变量的大小):

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

union Un
{
	char c;
	int i;
};

int main()
{
	union Un un = {0};
	printf("%d\n", sizeof(un));
	
	return 0;
}

🧐分析 :首先定义联合变量 un,初始化为 0;其中联合体大小至少是最大成员的大小 ;比如上面代码中最大成员为 int,占 4 字节,故输出 4

1.3特点

  1. 联合的成员共用同一块内存空间
  2. 一个联合变量的大小至少是最大成员的大小
  3. 对一个成员赋值,会覆盖其他成员的数据(互斥使用)

例如(观察下面 un.iun.cun 三个地址):

c 复制代码
#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;
}

运行结果:

我们可以看到三个地址输出完全相同 ,所以可以证明联合体变量、成员起始地址完全一致

我们进一步分析,将上面的代码修改一下,给 int i赋值,修改 char c 最后再打印 un.i ,看看会发生什么,如下所示:

c 复制代码
#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;
}

运行结果:

🧐分析 :给 i 赋值后,再修改 ci 的最低字节被改为 0x55;最后输出结果为11223355,证明内存共用、数据相互覆盖

1.4与相同成员结构体的对比

例如:

c 复制代码
struct S
{
	char c;
	int i;
};

union Un
{
	char c;
	int i;
};

🧐分析
结构体 :成员独立存放,有内存对齐,总大小更大
联合体:成员共用内存,无重叠浪费,总大小更小

总结

结构体适合同时使用多个成员 ,联合适合只使用一个成员

1.5联合体大小的计算

计算规则

  1. 联合的大小至少是最大成员的大小
  2. 当最大成员大小不是最大对齐数的整数倍时,要对齐到最大对齐数的整数倍

如下所示:

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

union Un1
{
	char c[5];
	int i;
};

union Un2
{
	short c[7];
	int i;
};

int main()
{
	printf("%d\n", sizeof(union Un1));
	printf("%d\n", sizeof(union Un2));

	return 0;
}

运行结果:

🧐分析

Un1:最大成员 char[5](5),最大对齐数 4 --> 对齐到 8

Un2:最大成员 short[7](14),最大对齐数 4 --> 对齐到 16

1.6判断机器大小端(利用联合体)

1.6.1什么是机器大小端:

大小端,是计算机在内存中存储多字节数据的两种顺序规则,只对超过1字节的数(int、short、float、指针等)有意义,单字节数据不存在大小端问题

小端 :低字节存低地址,高字节存高地址(低 --> 高)
大端:高字节存低地址,低字节存高地址(高 --> 低)

1.6.2实战

判断当前机器是大端存储还是小端存储(设置返回1为小端,返回0为大端)

c 复制代码
int check_sys()
{
	union
	{
		int i;
		char c;
	}un;

	un.i = 1;
	return un.c;
}

🧐分析

小端:低字节存低地址 --> c = 1

大端:高字节存低地址 --> c = 0

总结

利用联合体共用内存特性,最简判断大小端

二.枚举类型

枚举就是一一列举,把一个变量所有可能的取值列出来,用名字代表整数,让代码更清晰

2.1枚举类型的声明

例如:

c 复制代码
// 星期
enum Day
{
	Mon,//0
	Tues,//1
	Wed,//2
	Thur,//3
	Fri,//4
	Sat,//5
	Sun//7
};
// 颜色
enum Color
{
	RED,//0
	GREEN,//1
	BLUE//2
};

🧐分析 :其中 enum 是枚举关键字;{ } 内为枚举常量 ,是可能的取值;而且默认从 0 开始,依次递增 1

2.2枚举常量赋初值

举例(以上面颜色为例):

c 复制代码
enum Color
{
	RED = 2,
	GREEN = 4,
	BLUE = 8
};

🧐分析 :我们可以手动指定枚举常量的值;其中未指定的成员,会从上一个值继续 +1

2.3优点

  1. 增强代码可读性与可维护性:用名字代替魔法数字。
  2. 有类型检查 ,比 #define 更严谨安全。
  3. 便于调试#define 预处理会消失,枚举保留符号。
  4. 使用方便:一次可定义多个常量。
  5. 遵循作用域:枚举在函数内就只在函数内有效

2.4如何使用枚举

同样以颜色为例:

c 复制代码
enum Color
{
	RED = 1,
	GREEN = 2,
	BLUE = 4
};

int main()
{
	enum Color clr = GREEN;

	return 0;
}

🧐分析 :在这里枚举变量建议只用枚举常量赋值;在C语言可赋整数,但在C++禁止,类型检查更严格

🎯总结

联合体(union):

  1. 成员共用同一块内存,同一时间只用一个成员
  2. 大小 = 最大成员大小 + 内存对齐
  3. 典型用途:节省内存、大小端判断、协议解析

枚举(enum):

  1. 将固定取值一一列举,用名字表示常量
  2. 默认从 0 开始递增,可手动赋值
  3. #define 更规范、更安全、更易维护

⚠️易错点

  1. 混淆结构体与联合体:结构体独立存,联合体共用存
  2. 计算联合体大小时忘记内存对齐
  3. 误以为枚举可以随便用整数赋值(C++不行)
  4. 大小端判断程序逻辑错误,未正确使用联合特性
  5. 对联合体成员同时赋值、读取,导致数据错误
  6. 匿名联合体或匿名枚举使用时被编译器视为不同类型

👀 关注 我们一路同行,从入门到大师,慢慢沉淀、稳步成长
❤️ 点赞 鼓励原创,让优质内容被更多人看见
⭐ 收藏 收好核心知识点与实战技巧,需要时随时查阅
💬 评论 分享你的疑问或踩坑经历,一起交流避坑、共同进步

相关推荐
解救女汉子2 小时前
CSS3 按钮悬停时显示手型光标(cursor- pointer)的正确写法
jvm·数据库·python
wayz112 小时前
Day 10:集成学习进阶(Boosting: AdaBoost, GBDT)
算法·机器学习·集成学习·boosting
Little At Air2 小时前
C++stack模拟实现
linux·开发语言·c++·算法
csdn2015_2 小时前
spring boot 启动的时候将数据库里的分类信息写入redis
数据库·spring boot·redis
三品吉他手会点灯2 小时前
C语言学习笔记 - 9.C概述 - 常见问题答疑
c语言·笔记·学习
霸道流氓气质2 小时前
SpringBoot+LangChain4j+Ollama实现Function Calling工具调用-仿智能客服示例
java·spring boot·后端
张祥6422889042 小时前
导数与微分有啥区别
算法·数学建模
rayyy92 小时前
c++, sizeof(string)和string.size()有什么区别
c++
四维迁跃2 小时前
c++怎么在写入文件流时通过peek预读功能实现复杂的逻辑判断【实战】
jvm·数据库·python