【问题标题】:In C++, does the size of an enumeration have to be equal to the size of its underlying type?在 C++ 中,枚举的大小是否必须等于其底层类型的大小?
【发布时间】:2017-11-22 21:25:04
【问题描述】:

我经常假设枚举的大小与其底层类型的大小相同。但这是标准规定的吗?

标准 (C++14, n4296) 规定每个枚举都有一个基础类型 (7.2/5)。该标准还说对象被表示为字节序列,并且对象的大小与其表示有关:

3.9/4 T类型对象的对象表示是N的序列 类型 T 的对象占用的 unsigned char 对象,其中 N 等于 大小(T)。

5.3.3/1 sizeof 运算符产生对象中的字节数 其操作数的表示。

但是,我无法找到枚举的基础类型和对象表示之间的任何关系。有没有?如果不是,那么我认为枚举的 sizeof 不必是其底层类型的 sizeof。

所以我的问题是:

  1. 枚举的基础类型与其对象表示之间是否存在任何关系?

  2. 标准是否真的要求 sizeof(std::underlying_type_t<E>) == sizeof(E) 用于任何枚举 E?

【问题讨论】:

  • 我 99% 确定它们的大小必须相同。例如。有std::byte,就是enum class byte : unsigned char(不记得有符号或无符号),而且保证大小相同。不过,我不确定它在标准中的位置。
  • 否则会是什么尺寸?
  • @NeilButterworth 更大吗?它必须至少和 UT 一样大,因为它必须存储它的所有值。
  • 我认为有些参数说它可能更小 - 例如,如果一个枚举只有两个值,它可以存储在一个 char 中,但指定的基础类型可能是一个 int。请注意,我不是说这就是发生的事情。
  • @NeilButterworth 对于普通的旧 C 枚举(也就是 UT 不固定的无范围枚举)来说,这可能是正确的。

标签: c++ c++14 language-lawyer


【解决方案1】:

取自:What is the underlying type of a c++ enum?,7.2/5 中声明的旧 C++ 标准:

枚举的底层类型是一个整数类型,它可以 表示枚举中定义的所有枚举值。它是 实现定义使用哪种整数类型作为底层 枚举的类型,但基础类型不应是 大于 int 除非枚举器的值不能放入 整数或无符号整数。如果 enumerator-list 为空,则底层 type 就好像枚举有一个值为 0 的枚举数。 sizeof() 的值应用于枚举类型,即 枚举类型或枚举器,是 sizeof() 应用的值 到底层类型。

从draft n4606,我能找到的最接近的是 7.2/7 + 8,它指出:

7) 对于底层类型不固定的枚举,底层 type 是一个整数类型,可以表示所有枚举数值 在枚举中定义。如果没有整数类型可以代表所有 枚举值,枚举格式不正确。它是 实现定义使用哪种整数类型作为底层 类型,但基础类型不得大于 int 除非枚举器的值不能放入 int 或 unsigned 诠释。如果 enumerator-list 为空,则基础类型就像 枚举有一个值为 0 的枚举数。

8) 对于基础类型固定的枚举,枚举的值是 基础类型的值。否则,对于枚举 emin 是最小的枚举数,emax 是最大的, 枚举是 bmin 到 bmax 范围内的值,定义为 如下:对于二进制补码表示,令 K 为 1,对于 a 一个的补码或符号幅度表示。 bmax 是 大于或等于 max(|emin| - K, |emax|) 的最小值和 等于 2M - 1,其中 M 是非负整数。如果 bmin 为零 emin 是非负数,否则为 -(bmax + K)。的大小 足以容纳所有值的最小位域 如果 bmin 为零,则枚举类型为 max(M, 1),否则为 M + 1。它 可以定义具有未定义值的枚举 它的任何枚举数。如果 enumerator-list 为空,则 枚举就像枚举有一个单一的枚举器 值 0

一方面它看起来足够接近,另一方面,对sizeof() 运算符的特定需求被删除了。 尽管如此,我认为这两个问题的答案都是肯定的。

【讨论】:

    【解决方案2】:

    我已经搜索了标准,这是我能找到的最好的(我知道这可能不够):

    底层类型在这里隐式定义(C++14 的 3.9.1/5):

    类型 wchar_t 是一个 distinct 类型,其值可以表示 distinct 指定的最大扩展字符集的所有成员的代码 在受支持的语言环境 (22.3.1) 中。类型 wchar_t 应具有相同的 尺寸、签名和对齐要求 (3.11) 作为其中之一 其他整数类型,称为其基础类型。类型 char16_t 和 char32_t 表示具有相同大小、符号和 对齐为 uint_least16_t 和 uint_least32_t,分别在 ,称为底层类型。

    这个定义是关于wchar_t,但我认为可以肯定地说这是底层类型的定义。 (至少,这是标准给出的最好的定义。另外,底层类型的C++14标准索引参考这里)

    这意味着:

    1. 表示必须相同

    2. 大小必须相等

    (但我确实认为底层类型应该在标准中更好地定义)

    【讨论】:

    • 谢谢。我也发现了这个。它说“它的底层类型”,所以我会说它只为 wchar_t 定义了一个底层类型,其方式与枚举的 7.2/5 类似。
    • @JanTušil:是的,但文字略有不同。在这里,它“称为其基础类型”,因此可以解释为“基础类型具有这些属性,这就是定义”(不仅仅是 wchar_t)。对于枚举,他们不会这样说。但是,是的,也可以像您说的那样解释它。这里的标准不清楚,应该改进。即使您接受这个定义,1. 的答案也不是 100% 准确的,因为没有任何地方写明基础 repr 应该是相同的。但如果不是,那就很奇怪了(那为什么会有“底层”这个名字呢?)。
    • 我会说这句话只定义了 wchar_t 的“基础类型”
    • MM:我不清楚。 “基础类型”的索引在这里引用的事实支持这一定义。另一方面,它是在wchar_t 上下文中编写的,所以它可以只为wchar_t 定义。这个定义应该有它自己的要点。应该澄清这一点。但老实说,我不认为底层类型的定义应该因各种类型而异(我希望这也是委员会的意图)。 C++ 非常复杂,我们不要再复杂了。
    • 另外,我认为“相同的大小、签名和对齐要求”不能保证相同的表示。例如,一个枚举可能是大端,而底层类型是小端,这三个等价仍然成立。
    猜你喜欢
    • 2011-06-20
    • 1970-01-01
    • 1970-01-01
    • 2010-11-10
    • 1970-01-01
    • 2012-07-08
    • 1970-01-01
    相关资源
    最近更新 更多