【C/C++】自定义类型 枚举&联合

简介: 【C/C++】自定义类型 枚举&联合

学习导航


写在前面

枚举

枚举类型的定义

枚举的使用

枚举的大小计算

枚举的优点

联合(共用体)

联合类型的定义

联合的内存分配

联合大小的计算

写在前面


我们知道的C语言中的自定义类型有:

结构   位段   枚举   联合

接下来,我们一起学习剩余两种自定义类型。


正文


枚举


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

把可能的取值一一列举。

比如我们现实生活中:

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

性别有:男、女、保密,也可以一一列举。

月份有12个月,也可以一一列举


枚举类型的定义


enum Day//星期
{
    //枚举的可能取值
    //枚举的可能取值都是常量,不可修改
  Mon,    //注意是逗号
  Tues,
  Wed,
  Thur,
  Fri,
  Sat,
  Sun     //结尾并没有;
};
enum Sex//性别
{
  MALE,
  FEMALE,
  SECRET
};
enum Color//颜色
{
  RED,
  GREEN,
  BLUE
};


以上定义的 enum Day , enum Sex , enum Color 都是 枚举类型 。

{} 中的内容是枚举类型的可能取值,也叫 枚举常量 (常量不可修改但是可以赋初值)  。

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

当然在定义的时候也可以赋初值。

例如:


enum Color//颜色
{
  RED = 1,
  GREEN = 2,
  BLUE = 4
};

或者


enum Color//颜色
{
  RED = 1,
  GREEN,//2
  BLUE  //3
};

某个值复制后,后面的值如果没有赋值默认增加1。


枚举的使用


定义一个枚举类型的变量:


#include<stdio.h>
enum Color//颜色
{
  RED,
  GREEN,
  BLUE 
};
int main()
{
  enum Color col = RED;
    printf("%d", col);   //打印RED的值为0
  return 0;
}


既然RED的值为0,那我们能否将0赋值给col呢?

enum Color col = 0;//这样是否可行呢?


运行之后,我的编译器编译成功而且顺利运行。

但是并不代表这个语法在所有编译器下都是正确的。这取决与编译器对语法的容忍程度。

所以,只能拿枚举常量给枚举变量赋值,才不会出现类型的差异



枚举的大小计算


之前计算结构体的大小时,结构体的成员都有明确的类型,结合内存对齐的知识就可以得到结构体的大小。而我们发现枚举里的成员都是常量没有类型,甚至貌似都没有一条完整的语句,那该如何计算呢?


我们不妨先用sizeof求出它的大小:

printf("%d", sizeof(enum Color));

运行之后,其结果是4。

解释:

回顾之前介绍枚举类型,枚举{}里面所列的是枚举的可能取值。

例如定义该枚举类型的变量:

enum Color col = BLUE;

col只能是{}中枚举的可能取值中的任意一个

而之所以结果是4,是因为在我所使用的编译器下常量大小为4字节

到这里,我们可能会好奇,这个玩意有什么用啊?

我们用#define不也能定义常量吗?

#define RED 0
#define GREEN 1
#define BLUE 2

那我们就谈一谈枚举的优点。


枚举的优点


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

枚举的优点:

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

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

3. 防止了命名污染(封装)

4. 便于调试

5. 使用方便,一次可以定义多个常量

此外,今后我们利用枚举来设置程序的菜单会显得更加美观。


联合(共用体)


联合与结构非常的相似,主要区别就在于联合这两个字。

联合的特征:联合体所包含的成员变量使用的是同一块空间


联合类型的定义


直接看代码:


//联合类型的声明
union Un
{
  char c;
  int i;
};
//联合变量的定义
union Un un;

结果是 4

如果它是结构体的话,那么结果应该是 8

那我们就一起分析一下联合体的内存分配,看看差异从何而来。


联合的内存分配


有这样一个联合体类型:


union Un
{
  char c;
  int i;
  double  n;
};
union Un un;//定义变量


我们采用暴力的方法,直接打印un每个成员的地址看看:


int main()
{
  union Un un;
  printf("%p\n", &un);
  printf("%p\n", &un.c);
  printf("%p\n", &un.i);
  printf("%p\n", &un.n);
  return 0;
}

运行之后

3.png

它们的起始地址都相同,也就说明他们所用的其实就是同一块空间 。

4.png

这也就意味着,我们要改变任何一个成员变量的值,都会改变另外两个成员变量的值

例如:

现在un的i中存入0x11223344


int main()
{
  union Un un;
  un.i = 0x11223344;
  return 0;
}

image.png

然后改变un的c的值,看看内存如何变化:

un.c = 0x55;

image.png

果然如我们所想。


联合大小的计算


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

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

例如:


union Un1
{
  char c[5];
  int i;
};
union Un2
{
  short c[7];
  int i;
};
//下面输出的结果是什么?
printf("%d\n", sizeof(union Un1));
printf("%d\n", sizeof(union Un2));


结果如下:7.png

本章完



目录
相关文章
|
2月前
|
安全 算法 C++
【C/C++ 泛型编程 应用篇】C++ 如何通过Type traits处理弱枚举和强枚举
【C/C++ 泛型编程 应用篇】C++ 如何通过Type traits处理弱枚举和强枚举
53 3
|
2月前
|
存储 编译器 Shell
【C++基础语法 枚举】解析 C/C++ 中枚举类型大小值
【C++基础语法 枚举】解析 C/C++ 中枚举类型大小值
20 0
|
2月前
|
安全 算法 编译器
【C++ 泛型编程 入门篇】 C++ 模板元编程之枚举内嵌 实战教程
【C++ 泛型编程 入门篇】 C++ 模板元编程之枚举内嵌 实战教程
65 0
|
2月前
|
安全 算法 编译器
【C++基础语法 枚举】C/C++ 中enum枚举量的介绍:介绍enum枚举量在C/C中的作用和使用方法
【C++基础语法 枚举】C/C++ 中enum枚举量的介绍:介绍enum枚举量在C/C中的作用和使用方法
32 2
|
1月前
|
存储 算法 C++
第 284 场周赛(C++ | 枚举 | 分类讨论 | 最短路 | 建反图)
【4月更文挑战第1天】- [LeetCode 6031](https://leetcode-cn.com/problems/find-all-k-distant-indices-in-an-array/):给定数组 `nums`、键值 `key` 和距离 `k`,找到所有与键值相等且与任意下标距离不超过 `k` 的下标,返回升序排序的列表。找到最小权重。
29 0
|
2月前
|
算法 C++ UED
【Qt 常用枚举】深入解析C++中的AlignmentFlag枚举
【Qt 常用枚举】深入解析C++中的AlignmentFlag枚举
28 0
|
2月前
|
存储 安全 算法
【C/C++ std::memory_order 枚举】掌握 C++ 内存模型:深入理解 std::memory_order 的原理与应用
【C/C++ std::memory_order 枚举】掌握 C++ 内存模型:深入理解 std::memory_order 的原理与应用
59 0
|
2月前
|
编译器 数据安全/隐私保护 C++
C++系列十六:枚举
C++系列十六:枚举
|
2月前
|
存储 C++
C/C++自定义类型(详解struct,enum,union)
C/C++自定义类型(详解struct,enum,union)
|
5月前
|
机器学习/深度学习 人工智能 算法
C++011-C++循环+枚举
C++011-C++循环+枚举
C++011-C++循环+枚举