前言

enum枚举用于创建符号常量,通常用来替代const创建符号常量的方式。

定义枚举

一般有两种定义枚举的方式,第一种是设置枚举名,第二种是不设置枚举名(匿名)。

enum color {red, green, blue};  // 第一种
enum {red, green, blue};  // 第二种

其中, color 是枚举名; red, green, blue 是枚举量,默认从0开始,即: red = 0,green = 1,blue = 2 。

事实上,此时此刻的color就是一个数据类型了,可以利用它声明或定义变量——当然,没有枚举名也可以做到:

color skin;  // 利用枚举名声明变量skin,如果没有初始值,默认初始值为0
enum {red, green, blue} skin;  // 匿名枚举名 声明变量方式

赋值规则

对枚举类型的变量赋值时,规定 只能用枚举量 。对skin来说,赋值只能用 red,green,blue 。只不过, 也可以通过强制转换实现赋值 (不建议)。

color skin = blue;
// 等同于
color skin = color(2);

尽管枚举量是整型,但 直接把整型数字赋给枚举变量是错误的行为 :

color skin = 2;  // 错误

编译器报错: error: invalid conversion from ‘int’ to ‘color’ 。


对枚举来说, 只定义了赋值运算符,没有定义算术运算 。

color skin = red;  // 正确,允许此赋值方式
skin++;  // 错误,枚举类型没有加法运算
skin = 2 + red; // 错误,为什么错误后面再说

枚举量可以被提升(隐式转换)为int类型(反之不可以) :

int skin = red;  // 正确,但注意,现在的skin是int型,因此red被隐式转换成了int型
skin = red + green;  // 正确,因为red和green都被隐式的转换成了int型,因此可以相加
skin = green + 12;  // 正确

但下面的操作是错误:

color skin = red + blue;  // 错误

这是因为red和blue都被提升为了int型,二者相加的结果自然也是int,然而skin是枚举变量,不可以被int赋值。

枚举设值

枚举量默认从0开始,但也可以手动的设置枚举量的值,常用方法有以下三种:

  • 显示地定义 全部枚举量 的值:
enum {red = 5, green = 1, blue = 2};
  • 显示地定义 部分枚举量 的值,此时没有定义值的枚举量会基于前一个值加1:
enum {red = 5, green = 0, blue};
// 此时red = 5,green = 0, blue = 1
  • 允许存在多个 值相同的枚举量 :
enum {red = 0, green = 1, blue = 1};

事实上,枚举量不仅可以是int型,也可以是long、long long类型。

取值范围

尽管可以通过强制类型转换使得任意整型都可以赋值给枚举型变量——仅仅看上去是这样而已,但事实不是。 枚举类型的变量有默认的取值范围。

  • 最大值:首先找到枚举量中最大的值,包含这个值的最小的2的幂 - 1 就是该枚举类变量允许的最大值。如上述中的 enum {red = 5, green = 1, blue = 2}; ,最大值为5,那么包含5的最小2的幂是8,再减1,得到7。允许最大值是7。
  • 最小值:如果枚举量中,最小值不小于0,那么允许最小值为0。如果最小值小于0,则取这个值的绝对值,利用求最大值的方法求解,对最后的解加上负号。即,假如枚举中最小值为-6,则允许最小值是-7。

说明 :枚举的取值范围是我在《C++ Primer Plus》上看到的,然而经过测试,发现真实的运行结果并未受到取值范围约束。理论上最大只能取值7的时候,我对其赋值1000也没问题。难道是作者错了吗?

——事实上,我更愿意相信,取值范围的规定是为了让程序更“鲁棒”。所谓“君子不立墙角之下”,可行之事不代表可靠,作为程序员,你应该尽量不让程序处于危险之中。

  • Guan: 你是在哪儿看到报403的,我本地试了一下,可以正常访问,不过这个...
  • Veron: url=https://feed.hamibot.com/api...
  • Veron: 好东西,老Repo看着没更新怕用不了了,直接上你的版本,感谢:)
  • Guan: 这个很简单,你手动试一下就知道了
  • nigosim: 想请问一下,这个场景是B和网关还在同一网段,所以B仍能通过请求网...
  • youguanxinqing: scan 方法就是用来取值的
  • 第三: 但是取值却无法取啊
  • 九路: 测试
  • 396601500: 有用,帮到我了,谢谢
  • chauncey: 讲的很好,可以进一步讲一下vlan 和vxlan
  • Python 设计模式 Go MySQL vim c++ 继承 切片 指针 shell linux vscode 静态库 动态库 systemctl nginx rss 元类 类属性 私有属性 递归 汉诺塔 赏金问题 分支语句 循环语句 单例 跳转语句 赋值语句 defer type 项目管理 函数 闭包 结构体 数组 字典 异常机制 引用 方法 接口 匿名组合 排列 组合 动态规划 编辑距离 默认传参 递归中的参数 abc 抽象基类 ORM socket编程 简易聊天系统 select IO复用 并发编程 信号通道 enum vector std 友元 虚函数 动态联编 字符串处理 sed 平均负载 sftp 预处理 宏定义 条件编译 文件包含 操作符 预定义宏 其他命令 命名空间 导包 相对导入 pidstat vmstat 中断次数 上下文切换 lychee 编译 链接 mysqld ngx_fastdfs_module 真假值 去重 TypeError flutter 二分搜索 对角线问题 cpp 3n+1 缓存 mac 快捷键 终端 c centos7 docker 子域 主从配置 custom https http2 lychee-docker 创建型 django manjaro xfce databases k8s ssh log 网络 wireshark rust 多态 clickhouse 读书 编程 range 声明语句