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

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

  • 博客主页:向不悔
  • 本篇专栏:[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.xdnf.cn/news/9928.html

相关文章:

  • Python实例题:Python实现Zip文件的暴力破解
  • Spring Boot整活指南:从Helo World到“真香”定律
  • 29、请求处理-常用参数注解使用
  • UE路径追踪Path Tracing和Lumen的区别
  • Lambda表达式Stream流
  • 三套知识系统的实践比较:Notion、Confluence 与 Gitee Wiki
  • 关于 smali:2. 从 Java 到 Smali 的映射
  • 无需自建高防:APP遭遇DDoS的解决方案
  • CODEFORCES----1999A - A+B Again?
  • SQL进阶之旅 Day 7:视图与存储过程入门
  • vue的h函数(在 Vue 2中也称为 createElement)理解
  • SAP BASIS常用事务代码ST06 操作系统监控
  • UVa1384/LA3700 Interesting Yang Hui Triangle
  • OpenCv高阶(十九)——dlib关键点定位
  • 深度学习核心网络架构详解:从 CNN 到 LSTM
  • 关于DJI Cloud API Demo 终止维护公告-上云API源码停止维护
  • 文本预处理
  • 学习黑客小故事理解 Metasploit 的 Meterpreter
  • 【2025年电工杯数学建模竞赛A题】光伏电站发电功率日前预测问题+完整思路+paper+源码
  • BugKu Web渗透之备份是个好习惯
  • LeetCode Hot100(矩阵)
  • 逻辑回归知识点
  • stm32 + ads1292心率检测报警设置上下限
  • 鸿蒙分辨率
  • TDengine 运维——巡检工具(安装前检查)
  • 【Redis】第3节|深入理解Redis线程模型
  • 3.1.1栈的基本概念
  • 德国GEMÜ 3020特价型号3020 25D 7 1 4P002 3600
  • Java面试:从Spring Boot到分布式系统的技术探讨
  • VirtualBox安装 Rocky