【问题标题】:C++ enum to unsigned int comparisonC++ 枚举到无符号整数比较
【发布时间】:2008-11-19 11:28:01
【问题描述】:

我在目前正在处理的代码中发现了这一点,并认为这是我遇到一些问题的原因。

在某处的标题中:

enum SpecificIndexes{
    //snip
    INVALID_INDEX = -1
};

然后 - 初始化:

nextIndex = INVALID_INDEX;

并使用

if(nextIndex != INVALID_INDEX)
{
    //do stuff
}

调试代码,nextIndex 中的值不太有意义(它们很大),我发现它被声明了:

unsigned int nextIndex;

因此,INVALID_INDEX 的初始设置使 unsigned int 下溢并将其设置为一个巨大的数字。我认为这是导致问题的原因,但仔细观察,测试

if(nextIndex != INVALID_INDEX)

行为正确,即当 nextIndex 为“大 +ve 值”时,它从未执行 if 的主体。

这是正确的吗?这是怎么回事?枚举值是否被隐式转换为与变量相同类型的无符号整数,因此以相同的方式包装?

【问题讨论】:

  • ITYM “然后 - 分配”。初始化为unsigned nextIndex = INVALID_INDEX

标签: c++ enums comparison integer unsigned


【解决方案1】:

一切都好。 它是有效代码,也是常用的库端 C++ 代码,在现代 C++ 中更是如此(第一次看到时很奇怪,但在现实中它是一种非常常见的模式)。

然后枚举是有符号整数,但它们会隐式转换为无符号整数,现在这取决于您的编译器可能会发出警告,但它仍然非常常用,但是您应该显式转换以使维护人员清楚。

【讨论】:

  • 我完全不同意。首先,您的代码说 nextIndex 是无符号的,而实际上它不是,这会误导读者。其次,如果您稍后决定向 SpecificIndexes 添加新的正值并使用运算符 > 或
  • 枚举已签名,但您对 >
  • 是的 - 这是我发现的一个问题。使用 nextIndex 的函数断言它 > 0,因此将其更改为使用带符号的 int 并不是一个简单的选择,我认为其他代码依赖于它的实现方式。这很令人困惑。
  • 闻起来像重构我的时间:) 无论如何,一个快速的解决方案是 Assert(index>0 && index != INVALID_INDEX);至少这是正确的,并且也使断言得到了更好的记录。
【解决方案2】:

枚举可以由有符号或无符号整数类型表示,具体取决于它们是否包含任何负值以及编译器的感觉。这里的例子包含一个负值,因此必须用有符号整数类型表示。

有符号和无符号类型之间的相等比较是安全的,并且通常按照作者的意图进行 - 有符号值将首先转换为无符号,并且这样做的结果由 C++ 标准定义并且是直观的(至少,它是一旦你知道目标类型。除非整数不是二进制补码。所以可能不是那么直观,但通常不会导致问题。

订单比较更有可能导致错误。例如:

SpecificIndexes value = INVALID_VALUE;
return (value >= 0);

返回 false,但是:

unsigned int value = INVALID_VALUE;
return (value >= 0);

返回真。有时作者不会欣赏这种差异,特别是如果“价值”的类型在使用时不是很明显。不过,编译器可能会对第二个示例发出警告,因为 (value >= 0) 是重言式。

【讨论】:

    【解决方案3】:

    事实上,当-1 被赋值给nextValue 时,它​​被隐式地转换为它的等价无符号值。等价的无符号是具有相同按位表示的值(即 111111111111...,这是最大的无符号值)。

    稍后,在比较语句中,发生了另一个隐式转换。

    所以这现在可以工作,但将来可能会导致问题。混合有符号和无符号值绝不是一个好主意。

    【讨论】:

    • 那么使用枚举值的测试呢,我认为这也是一个隐式转换?
    • 为了记录,我同意 xan 的观点并相应地编辑了我的条目。但我不知道为什么我的评论消失了。
    • “等价的无符号是具有相同按位表示的值” - 如果实现对有符号整数类型使用二进制补码表示,则这是正确的。然而,这不是定义,也不适用于补码或符号值表示。反正很少见。
    【解决方案4】:

    是的,我相信枚举已签名。改变

    unsigned int nextIndex;
    

    int nextIndex;
    

    你的程序应该可以工作了。

    【讨论】:

    • 它按原样工作(它是现有系统的一部分,而不是我从头开始编写的东西) - 我的问题是 为什么 它像看起来那样工作大错特错!
    【解决方案5】:

    C++ 标准允许实现对枚举使用有符号类型,但并不要求这样做。因此,您通常不能假设将负数放入枚举中是安全的。

    【讨论】:

      猜你喜欢
      • 2023-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-19
      • 2013-02-04
      • 1970-01-01
      • 1970-01-01
      • 2017-12-03
      相关资源
      最近更新 更多