联合体和枚举类型

2024-06-09 11:44
文章标签 类型 枚举 联合体

本文主要是介绍联合体和枚举类型,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.联合体

1.1 联合体类型的声明

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

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

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

1.2联合体的特点

  • 联合的成员是共用同⼀块内存空间的,这样⼀个联合变量的大小,至少是最大成员的大小(因为联合至少得有能力保存最大的那个成员)。

  • 我们看如下代码,&un 和 &un.i 和 &un.c 的地址是同一个地址,我们可以得出char 和int 公用一个内存空间 4

union Un {char c;int i;
};
​
int main() {union Un un = {0};printf("%zd", sizeof(un));printf("%zd", &un);printf("%zd", &un.c);printf("%zd", &un.i);
}

1.3联合体大小计算

  • 联合的大小至少是最大成员的大小。

  • 当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。

我们看如下代码 最大成员大小为 5 不是4的倍数 那就浪费三个字节 最后占8个字节

union Un {
​char c[5];// 等于5个char类型 对齐数是1 8(最大) 1int i;//3                         4 8      4//然后 5不是4的倍数 那就浪费三个字节 最后占8个字节
​
};
int main() {printf("%zd", sizeof(union Un));
}

1.4什么场景使用联合体?

使用联合体是可以节省空间的,举例:

比如,我们要搞⼀个活动,要上线⼀个礼品兑换单,礼品兑换单中有三种商品:图书、杯⼦、衬衫。

每⼀种商品都有:库存量、价格、商品类型和商品类型相关的其他信息。

图书:书名、作者、页数

杯⼦:设计

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

那我们不思考,直接写出⼀下结构:

struct gift_list
{//公共属性int stock_number;//库存量double price; //定价int item_type;//商品类型
​char title[20];//书名char author[20];//作者int num_pages;//⻚数char design[30];//设计int colors;//颜⾊int sizes;//尺⼨
};

上述的结构其实设计的很简单,⽤起来也⽅便,但是结构的设计中包含了所有礼品的各种属性,这样使得结构体的大小就会偏大,比较浪费内存。因为对于礼品兑换单中的商品来说,只有部分属性信息是常用的。比如:商品是图书,就不需要design、colors、sizes。

所以我们就可以把公共属性单独写出来,剩余属于各种商品本⾝的属性使用联合体起来,这样就可以介绍所需的内存空间,⼀定程度上节省了内存。

  • 用联合体类型的话,他们私有的属性就独立出来了,内存总共就给他们一个空间,然后他们共用一份空间,谁用的时候就占用这一份空间(使用的时候才创建),那就在一定程度上节省了空间

  • 结构体用匿名类型

  • 访问的时候 先找到gift_list结构体再找item 最后找你想要的

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;
};
  • 接下来我们回忆一下前面判断机器大小端的练习,现在我们用联合体去判断


union  Un
{char c;int i;
};
​
int main() {union Un u = { 0 }; //初始化u.i = 1;if (u.c == 1) {printf("小端");}else{printf("大端");}
}

2.枚举类型

2.1枚举类型声明

枚举顾名思义就是⼀⼀列举。

把可能的取值⼀⼀列举。

比如我们现实生活中:

⼀周的星期⼀到星期日是有限的7天,可以⼀⼀列举

性别有:男、女、保密,也可以⼀⼀列举 等等

这些数据的表示就可以使用枚举了。

{ }中的内容是枚举类型的可能取值,也叫 枚举常量 。

这些可能取值都是有值的,默认从0开始,依次递增1

//枚举类型
enum Sex {MALE,FEMALE,SECRET
​
};
​
int main() {enum Sex sex1 = MALE;printf("%d\n", MALE);printf("%d\n", FEMALE);printf("%d\n", SECRET);
}
当然在声明枚举类型的时候也可以赋初值,第一个常量永远是0其他的一次递增enum Sex {MALE,FEMALE=2,SECRET=
​
};
​
int main() {enum Sex sex1 = MALE;printf("%d\n", MALE);printf("%d\n", FEMALE);printf("%d\n", SECRET);
}
  • 我们会疑惑,为什么常量可以修改呢? 这并不是修改,只是给一个初始值,我们可以看到以下的赋值语句 MALE = 5 报错

//枚举类型
enum Sex {MALE,FEMALE=2,SECRET=3
​
};
​
int main() {enum Sex sex1 = MALE;MALE = 5; //这里不能赋值成功 修改失败printf("%d\n", MALE);printf("%d\n", FEMALE);printf("%d\n", SECRET);
}

2.2 枚举类型的优点

为什么使用枚举?

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

枚举的优点:

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

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

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

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

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

下面举一个加法器的例子体现枚举类型的优点,定义一个枚举类型可以让代码更有可读性

//定义一个枚举类型 提高代码的可读性
enum Option {EXIT = 0,ADD,SUB,MUL,DIV
};
​
void menu() {printf("***********************************");printf("********1.add   2.sub**************");printf("********3.mul   4.div**************");printf("********    0.exit   **************");
}
int main() {int input = 0;do {menu();printf("请选择你想要的计算:");scanf("%d", &input);switch (input){case ADD:  //方法名 比 1, 2 ,3 更有可读性,便于理解Add();break;case SUB:Sub();break;case MUL:Mul();break;case DIV:Div();break;case EXIT:break;default:printf("选择有误,请重新选择");}} while (input);
​
}

这篇关于联合体和枚举类型的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1045086

相关文章

Mysql 中的多表连接和连接类型详解

《Mysql中的多表连接和连接类型详解》这篇文章详细介绍了MySQL中的多表连接及其各种类型,包括内连接、左连接、右连接、全外连接、自连接和交叉连接,通过这些连接方式,可以将分散在不同表中的相关数据... 目录什么是多表连接?1. 内连接(INNER JOIN)2. 左连接(LEFT JOIN 或 LEFT

Java 枚举的常用技巧汇总

《Java枚举的常用技巧汇总》在Java中,枚举类型是一种特殊的数据类型,允许定义一组固定的常量,默认情况下,toString方法返回枚举常量的名称,本文提供了一个完整的代码示例,展示了如何在Jav... 目录一、枚举的基本概念1. 什么是枚举?2. 基本枚举示例3. 枚举的优势二、枚举的高级用法1. 枚举

Redis的Hash类型及相关命令小结

《Redis的Hash类型及相关命令小结》edisHash是一种数据结构,用于存储字段和值的映射关系,本文就来介绍一下Redis的Hash类型及相关命令小结,具有一定的参考价值,感兴趣的可以了解一下... 目录HSETHGETHEXISTSHDELHKEYSHVALSHGETALLHMGETHLENHSET

结构体和联合体的区别及说明

《结构体和联合体的区别及说明》文章主要介绍了C语言中的结构体和联合体,结构体是一种自定义的复合数据类型,可以包含多个成员,每个成员可以是不同的数据类型,联合体是一种特殊的数据结构,可以在内存中共享同一... 目录结构体和联合体的区别1. 结构体(Struct)2. 联合体(Union)3. 联合体与结构体的

Rust中的Option枚举快速入门教程

《Rust中的Option枚举快速入门教程》Rust中的Option枚举用于表示可能不存在的值,提供了多种方法来处理这些值,避免了空指针异常,文章介绍了Option的定义、常见方法、使用场景以及注意事... 目录引言Option介绍Option的常见方法Option使用场景场景一:函数返回可能不存在的值场景

Python中异常类型ValueError使用方法与场景

《Python中异常类型ValueError使用方法与场景》:本文主要介绍Python中的ValueError异常类型,它在处理不合适的值时抛出,并提供如何有效使用ValueError的建议,文中... 目录前言什么是 ValueError?什么时候会用到 ValueError?场景 1: 转换数据类型场景

C# dynamic类型使用详解

《C#dynamic类型使用详解》C#中的dynamic类型允许在运行时确定对象的类型和成员,跳过编译时类型检查,适用于处理未知类型的对象或与动态语言互操作,dynamic支持动态成员解析、添加和删... 目录简介dynamic 的定义dynamic 的使用动态类型赋值访问成员动态方法调用dynamic 的

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

hdu 2489 (dfs枚举 + prim)

题意: 对于一棵顶点和边都有权值的树,使用下面的等式来计算Ratio 给定一个n 个顶点的完全图及它所有顶点和边的权值,找到一个该图含有m 个顶点的子图,并且让这个子图的Ratio 值在所有m 个顶点的树中最小。 解析: 因为数据量不大,先用dfs枚举搭配出m个子节点,算出点和,然后套个prim算出边和,每次比较大小即可。 dfs没有写好,A的老泪纵横。 错在把index在d

自定义类型:结构体(续)

目录 一. 结构体的内存对齐 1.1 为什么存在内存对齐? 1.2 修改默认对齐数 二. 结构体传参 三. 结构体实现位段 一. 结构体的内存对齐 在前面的文章里我们已经讲过一部分的内存对齐的知识,并举出了两个例子,我们再举出两个例子继续说明: struct S3{double a;int b;char c;};int mian(){printf("%zd\n",s