[C]基础18.自定义类型:联合和枚举

article/2025/8/26 15:54:36
  • 博客主页:向不悔
  • 本篇专栏:[C]
  • 您的支持,是我的创作动力。

文章目录

  • 0、总结
  • 1、联合体(共用体)
    • 1.1 联合体类型的声明
    • 1.2 联合体的特点
    • 1.3 联合体大小的计算
    • 1.4 联合体的应用场景
    • 1.5 联合体练习:判断机器字节序
  • 2、枚举类型
    • 2.1 枚举类型的声明
    • 2.2 枚举常量的值
    • 2.3 枚举类型的优点
    • 2.4 枚举类型的使用
  • 3、其他
    • 3.1 深入理解:联合体的内存布局
    • 3.2 枚举与#define的比较
    • 3.3 实际应用建议


0、总结

在这里插入图片描述

1、联合体(共用体)

1.1 联合体类型的声明

联合体(union)是一种特殊的数据类型,允许在相同的内存位置存储不同的数据类型。与结构体类似,联合体也是由一个或多个成员组成,但这些成员共享同一块内存空间。

union Un {char c;int i;
};

1.2 联合体的特点

  • 内存共享:所有成员共用同一块内存空间
  • 大小确定:联合体的大小至少是其最大成员的大小
  • 值覆盖:给一个成员赋值会影响其他成员的值

示例代码1

 union Un un = { 0 };printf("%p\n", &(un.i));  // 输出地址printf("%p\n", &(un.c));  // 输出相同地址printf("%p\n", &un);      // 输出相同地址
运行:
0000005805BBFA24
0000005805BBFA24
0000005805BBFA24

示例代码2(展示值覆盖):

un.i = 0x11223344;
un.c = 0x55;
printf("%x\n", un.i);  // 输出修改后的值
运行:
11223355

1.3 联合体大小的计算

  • 联合体大小至少是最大成员的大小
  • 当最大成员大小不是最大对齐数的整数倍时,需要对齐到最大对齐数的整数倍

示例

union Un1 {char c[5];  // 大小5,对齐数1int i;      // 大小4,对齐数4
};  // 最终大小为8(对齐到4的倍数)union Un2 {short c[7]; // 大小14,对齐数2int i;      // 大小4,对齐数4
};  // 最终大小为16(对齐到4的倍数)

1.4 联合体的应用场景

使用联合体是可以节省空间的,举例:比如,我们要搞一个活动,要上线一个礼品兑换单,礼品兑换单中有三种商品:图书、杯子、衬衫。每一种商品都有:库存量、价格、商品类型和商品类型相关的其他信息。

图书:书名、作者、页数

杯子:设计

衬衫:设计、可选颜色、可选尺寸

问题描述:如果直接将所有属性都放在一个结构体中,会导致结构体大小偏大,浪费内存。因为对于每种商品来说,只有部分属性是常用的。例如,图书不需要设计、颜色、尺码等属性。

解决方案:将公共属性单独提取出来,将每种商品独特的属性放入联合体中。这样可以减少结构体的大小,节省内存空间。

礼品兑换单示例

struct gift_list {int stock_number;  // 库存量double price;      // 定价int item_type;     // 商品类型union {struct {char title[20];  // 书名char author[20]; // 作者int num_pages;  // 页数} book;struct {char design[30]; // 设计} mug;struct {char design[30]; // 设计int colors;      // 颜色int sizes;        // 尺寸} shirt;} item;
};

1.5 联合体练习:判断机器字节序

int check_sys() {union {int i;char c;} un;un.i = 1;return un.c;  // 返回1是小端,返回0是大端
}

2、枚举类型

2.1 枚举类型的声明

枚举类型用于定义一组命名的整数常量,使代码更易读。

enum Day { Mon, Tues, Wed, Thur, Fri, Sat, Sun };
enum Sex { MALE, FEMALE, SECRET };
enum Color { RED, GREEN, BLUE };

2.2 枚举常量的值

  • 默认从0开始,依次递增1
  • 可以手动指定初始值
enum Color { RED=2, GREEN=4, BLUE=8 };

2.3 枚举类型的优点

  • 可读性和可维护性:使用有意义的名称代替数字

  • 类型检查:比#define定义的常量更安全

  • 调试友好:枚举常量在调试时可见,而#define宏在预处理阶段已被替换

  • 作用域规则:遵循常规的作用域规则

  • 批量定义:可以一次定义多个相关常量

2.4 枚举类型的使用

enum Color clr = GREEN;  // 正确使用
// clr = 2;  // 在C中可能允许,但在C++中不允许

3、其他

3.1 深入理解:联合体的内存布局

联合体的所有成员共享同一块内存空间,这意味着:

  • 内存覆盖:修改一个成员会覆盖其他成员的值

  • 类型解释:同一内存块可以用不同数据类型解释

例如,在判断字节序的例子中,我们利用联合体的这一特性,通过int和char两种类型访问同一内存位置,从而判断系统是小端序(低位字节在前)还是大端序(高位字节在前)。

3.2 枚举与#define的比较

虽然#define也可以定义常量,但枚举有以下优势:

  1. 类型安全:枚举常量有明确的类型,编译器可以进行类型检查
  2. 调试信息:枚举常量在调试器中可见,而宏定义已被预处理替换
  3. 作用域控制:枚举可以定义在函数内部,限制作用域
  4. 自动赋值:枚举可以自动递增赋值,减少手动赋值的工作量

3.3 实际应用建议

联合体

  • 用于需要节省内存的场景
  • 处理不同类型数据的互斥访问
  • 实现类似C++中variant的类型安全联合

枚举

  • 替代魔法数字,提高代码可读性
  • 表示有限的状态集合
  • 作为函数参数限制输入范围

总结:

  • 联合体和枚举是C语言中强大的自定义类型工具。
  • 联合体通过内存共享实现灵活的数据表示,特别适合内存敏感的应用。
  • 枚举则通过命名常量提高了代码的可读性和安全性。
  • 理解它们的特性和适用场景,可以帮助我们编写更高效、更易维护的C语言代码。

http://www.hkcw.cn/article/IKbAIIrKqQ.shtml

相关文章

目标检测预测框置信度(Confidence Score)计算方式

预测框的置信度(Confidence Score)是目标检测模型输出的一个关键部分,它衡量了模型对一个预测框中包含特定类别对象的确定程度。 不同的目标检测模型(如Faster R-CNN、SSD、YOLO、DETR等)在计算置信度时有其特有的机制…

视觉分析开发范例:Puppeteer截图+计算机视觉动态定位

一、选型背景:传统爬虫已无力应对的视觉挑战 在现代互联网环境中,尤其是小红书、抖音、B站等视觉驱动型平台,传统基于 HTML 的爬虫已经难以满足精准数据采集需求: 内容加载由 JS 动态触发,难以直接解析 HTML&#xf…

Java 开发上门家政系统源码:全流程数字化管理,适配家政公司 / 个体户接单派单

家政服务订单管理混乱、人员调度低效、客户留存率低?基于 Java 开发的上门家政系统源码,凭借其强大的稳定性、灵活的扩展性和全流程数字化管理能力,为家政行业提供了一套高效、低成本的解决方案,实现从接单、派单到服务结算的全链…

java24

1.双列集合Map定义 collection和Map都自有contains方法 把实现类对象赋值给接口类对象属于多态的一种,但是这样不能使用实现类里面的特殊方法和重写方法 写好的API里面好像只有数组的打印值是地址值 2.Map遍历方式 Entry是Map接口里面的一个内部接口,所…

VSCode的下载与安装(2025亲测有效)

目录 0 前言1 下载2 安装3 后记 0 前言 丫的,谁懂啊,尝试了各种办法不行的话,我就不得不拿出我的最后绝招了,卸载,重新安装,我经常要重新安装,所以自己写了一个博客,给自己&#xf…

深入了解linux系统—— 库的制作和使用

什么是库? 库,简单来说就是现有的,成熟的代码; 就比如我们使用的C语言标准库,我们经常使用输入scanf和输出printf,都是库里面给我们实现好的,我们可以直接进行服用。 库呢又分为静态库和动态…

VoltAgent 是一个开源 TypeScript 框架,用于构建和编排 AI 代理

​一、软件介绍 文末提供程序和源码下载 VoltAgent 是一个开源 TypeScript 框架,用于构建和编排 AI 代理 二、什么是 VoltAgent? AI 代理框架提供了构建由自主代理提供支持的应用程序所需的基础结构和工具。这些代理通常由大型语言模型 (&am…

弹性公网IP的五大核心优势解析

在云服务架构中,弹性公网IP(EIP)已成为现代企业网络部署的核心组件。与传统固定IP相比,它通过独特的技术机制解决了动态环境下的公网访问难题。以下五大核心优势决定了其不可替代的价值: 一、动态绑定的灵活性 弹性公…

分布式数据库备份实践

在分布式备份中可以采取两种方式进行备份,一种是采用手动编写backup.yml文件进行备份,另外一种是吧备份过程交给备份工具自动执行。如果需要个性化进行备份,建议采用手动编写备份文件方式进行备份。 以下是针对两种备份方式的实践&#xff1a…

社群分享:义乌|杭州电商|店群卖家,私域鱼塘运营的排单系统开源|私域鱼塘运营|返款软件开源

熟悉东哥的朋友都知道,我自己也运营一个电商社群,主要是针对玩私域|鱼塘的电商玩家。 在当前电商环境下,社群分享型电商、店群卖家及私域鱼塘运营者,面临着日益复杂的订单管理和客服调度问题。传统的人工处理不仅效率低…

一键提取Office内图片的工具

软件介绍 OfficeImagesExtractor是一款专门用于提取office文档里面图片的软件。 软件开发 这款软件是由吾爱大佬namejm专门开发的。 软件使用方法 该软件使用起来非常简单。用户只需要把文件拖入到软件里,再设置好保存目录即可。 支持文件格式 这款软件能提取的…

NVIDIA英伟达AI图片视频内容描述总结软件describe-anything整合包

和大家分享一个英伟达联合其他大学开发的一款应用describe-anything,该应用可以通过AI识别分析并详细描述图片视频中指定区域物体内容,我基于最新版制作了免安装一键启动整合包,下载链接在文章末尾。 describe-anything介绍 Describe Anythi…

农村土地承包经营权二轮延包—归户表

"作为二轮延包公示后的一个确认方式,归户表还是要写一下的。归户表跟摸底表很相似,编程方面,用到的python库,摸底表用py-docx多一些,归户表更多用的pywin32,py-docx对于word无依赖,所以摸底…

基于vue框架的独居老人上门护理小程序的设计r322q(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。

系统程序文件列表 项目功能:用户,护理人员,服务预约,服务评价,服务类别,护理项目,请假记录 开题报告内容 基于Vue框架的独居老人上门护理小程序的设计开题报告 一、研究背景与意义 (一)研究背景 随着社会老龄化的加剧,独居老…

window11系统 使用GO语言建立TDengine 连接

目录 1、安装GCC、TDengine-client 1、github下载mingw64 软件包 2、解压指定目录、配置环境变量 3、检验gcc是否安装成功 4、安装TDengine-client 2、配置go环境变量 3、配置Goland 系统变量、重启Goland(该软件自己也有系统变量,有时候会和win…

OpenCV计算机视觉实战(9)——阈值化技术详解

OpenCV计算机视觉实战(9)——阈值化技术详解 0. 前言1. 全局阈值与自适应阈值2. Otsu 算法3. 实战案例:文档扫描中的二值化处理4. 算法对比小结系列链接 0. 前言 在图像处理领域,阈值化 (Binarization) 技术就像一把魔术剪刀&…

Java开发经验——阿里巴巴编码规范实践解析6

摘要 本文深入解析了阿里巴巴编码规范在数据库设计和Java开发中的实践应用。详细阐述了数据库字段命名、类型选择、索引命名等规范,以及Java POJO类的对应规范。强调了字段命名的重要性,如布尔字段命名规则、表名和字段名的命名禁忌等。同时&#xff0c…

华为防火墙NAPT配置

1.实验拓扑 2.实验配置 [SW1]dis cu # sysname SW1 # vlan batch 10 20 # interface Vlanif10ip address 192.168.10.254 255.255.255.0 # interface Vlanif20ip address 192.168.20.253 255.255.255.0 # interface GigabitEthernet0/0/1port link-type accessport default vl…

HTML Day03

Day03 0. 引言1. CSS1.1 CSS的3种使用方法1.2 内联样式1.3 内部样式表1.4 外部CSS文件 2. 图像3. 表格3.1单元格间距和单元格边框 4. 列表4.1 有序表格的不同类型4.2 不同类型的无序表格4.3 嵌套列表 5. 区块6. 布局6.1 div布局6.2 表格布局 0. 引言 HELLO ^ _ ^大家好&#xf…

【Redis】背景知识 + 环境搭建

背景知识 环境搭建 一. Redis 特性二. Redis 应用场景三. 环境搭建四. Redis 客户端介绍五. Redis 总结 Redis 是一个在内存中存储数据的中间件,用于作为数据库,用于作为数据缓存,用于作为消息队列,在分布式系统中能够大展拳脚。…