为什么isocpp允许我们超过枚举类值
Why isocpp allows us to exceed enum class values?
我在编程时发现了许多有趣的东西,其中之一是:
enum class Foo {
FOO_THING,
FOO_TOO
};
int main() {
Foo foo {'d'}; // It is OK
Foo foo2 {3}; // and that one too
}
调试器说它的值是:
foo: (unknown: 100)
foo2: (Foo::FOO_TOO | unknown: 2)
你能告诉我,为什么允许使用超过声明的枚举类值来初始化Foo
吗?
编译器版本和命令:
Compiler GCC (g++ (Ubuntu 7.3.0-21ubuntu1~16.04) 7.3.0)
$ g++ -Wall -std=c++17 foo.cpp
我真的想知道在 C++17 中创建该初始化机制的原因吗?
据我所知,枚举类是创建的,不允许用户以这种方式使用枚举。
告诉我,为什么允许用超过 声明的枚举类值?
正如其他答案之一所说 - 枚举是引擎盖下的整数。特定于实现的是,哪种整数类型用于特定的枚举。这就是为什么您可以将整数分配给枚举的原因。
据我所知,枚举类是创建的,不允许用户使用 以这种方式枚举。
这实际上是不正确的 - 枚举类的存在无法隐式地将枚举转换为整数,而不是相反。请注意,将int
隐式强制转换为clas enum
不会构成太大可能的威胁。
请注意,显式强制转换是完全有效的,有时很有用。
枚举作为位标志
有时枚举可以用作位标志
enum class O{
NOTHING = 0,
VERBOSE = 1,
QUIET = 2,
LOG = 4
};
现在假设你想要传递你的选项,但你希望你的输出被记录和详细。所以你应该通过 4 |1 = 5。这超出了枚举值。对我来说,它只有效(在某种程度上,这个问题有更好的解决方案)使用超过最大值的class enum
。
每个enum class
都有一个基础类型,该类型必须至少有一个字节大。任何像'd'
这样的单字符常量都适合一个字节。
(C++将字节定义为一个字符的存储量。 8位在C++行话中称为"八位组")
请注意,对于"旧"枚举,范围的定义更严格,但这会影响转换规则。你仍然有一个基础类型,它仍然必须是一个字节大。
[dcl.enum]/8:
对于基础类型为固定的枚举,枚举的值是基础类型的值。
所有enum class
都有一个固定的基础类型;显式或 int(如果未显式给出)。
因此,他们保证能够存储其底层类型可以存储的任何内容。
无作用域枚举(enum
没有class
或struct
)有不同的规则;它们的有效值基本上是枚举器值的2s补码二进制立方体。 如果枚举未限定范围,则将其值设置为 3 将无法移植。
我怀疑这个作用域枚举的规则是为了更容易地检查某种意义上的正确性;它们保证是某种整体类型。 检查无作用域枚举使用的正确性很困难。 这确实意味着作为程序员,您不能假设枚举仅处于其枚举值的状态;但是确保这样做既会破坏枚举的许多用例,又很难实际保证。
你可能会提出一个严格的枚举的建议,如果你从中看到它的巨大优势,它只能在命名状态中。
对于非作用域枚举:[dcl.enum] 7.2/8
对于基础类型为固定的枚举,枚举的值是 基础类型。 否则,对于其中的枚举 e_min 是最小的枚举器,并且 e_max 是 最大,枚举的值是范围内的值 b_min 自 b_max ,定义如下:让 K对于二的补码表示为 1,对于一的补码或符号大小表示为 0。 b_max 是大于或等于的最小值 .max ( | e_min |− K, | e_max | ) 并等于 2^M − 1 哪里 M 是一个非负整数。 b_min 为零,如果 e_min 是非负的,并且 − ( b_max + K ) 否则。的大小 足以容纳枚举类型的所有值的最小位字段是 .max ( M, 1) 如果 b_min 是 零和 M + 1 否则。可以定义一个枚举,该枚举的值未由其任何定义 统计员。如果 枚举器列表 为空,枚举的值就像枚举具有 值为 0 的单个枚举器
[expr.static.cast] 5.2.8/10:
整型或枚举类型的值可以显式转换为枚举类型。值为如果原始值在枚举值 (7.2) 的范围内,则保持不变。否则,结果 值未指定(可能不在该范围内)。
转换为枚举值的二进制闭包之外的非作用域枚举会导致未指定的值,即使它适合基础类型也是如此。
enum foo{zero, one};
foo
的基础类型将是某种整型类型,并且foo
与该整型布局兼容,并且该整型类型可能只保存2
文件,但将 2 转换为foo
会导致foo
存储未指定的值。
- 不带大括号的枚举形式
- 枚举环境变量的惯用C++14/C++17方法
- 类似枚举的计算常量
- 如何正确实现和访问运算符的各种自定义枚举器
- 错误:从"int"到枚举c++的转换无效
- C++中构造函数中的枚举
- 访问在 C++ 结构中声明的枚举变量
- 枚举类'classname'的多重定义
- 强枚举类型定义:Clang Bug 还是 C++11 标准不确定性?
- typedef 枚举和枚举类有什么区别?
- 为什么我的开关/机箱在使用枚举时默认?
- 标准::可选枚举的比较运算符
- C++两个源文件之间共享的枚举的静态实例
- 打印没有铸件的枚举可以在C++中吗?
- 枚举成员与静态 int 成员?
- 我们应该如何使用枚举类进行索引(或者我们应该更好地避免这种情况)?
- 为什么isocpp允许我们超过枚举类值
- 我们可以专业化类模板的枚举(类型)成员吗?
- 在这种情况下,我们在C中的枚举中只定义一个成员
- 我们可以在函数中定义枚举吗?