【问题标题】:C++ - Right shift not evaluated correctly inside IF [closed]C++ - 在 IF 内未正确评估右移 [关闭]
【发布时间】:2017-08-26 07:49:12
【问题描述】:

我有以下代码,

if (index > ((v.size() >> 1) - 1)) { }

v.size() 为 0,index 为 1。执行不会进入 if 块。但是如果我把上面的代码改成,

int limit = (v.size() >> 1) - 1;
if (index > limit) { }

在 v.size() 和 index 的值相同的情况下,执行确实进入了 if 块。

为什么会发生这种行为?谢谢。

【问题讨论】:

  • 可能是因为v.size() 不是int。但我们不知道它的作用,因为您的代码中缺少相关上下文。
  • 啊,忽略警告...
  • 这是由于隐式转换为无符号类型。第二种方法实际上是强制转换。好问题:我不明白反对票。
  • @Bathsheba 这个问题没有显示任何研究工作,并且不清楚因为所有重要部分(indexv.size() 的类型)都丢失了。
  • 对于大一新生来说,这种行为是如此奇特,以至于很难知道如何开始这项研究。如果 OP 怀疑它是由类型决定的,那么这篇文章几乎是修辞——尽管这本身并没有错。我很确定我的许多最佳答案都是针对反问的。

标签: c++


【解决方案1】:

您显然是在执行无符号比较。 v.size() 的返回类型很可能是 size_t,它是一个无符号整数。因此,表达式(v.size() >> 1) - 1 产生最大可能的无符号整数。除非您将其转换回有符号整数类型,否则您不会得到肯定的比较结果。

在减法之前简单地转换为ssize_t 将解决您的问题:

if (index > (((ssize_t)v.size() >> 1) - 1)) { }

我使用了ssize_t,因为该类型保证能够保存任何size_t 值,如果设置了最高有效位,则将其重新解释为负数。 int 不能这么说,因为在 64 位平台上通常只有 32 位。因此,像您在第二个示例中所做的那样使用 int 可能会截断一些位。

【讨论】:

  • 我不敢相信人们仍然会出错,您必须在 减法之前转换为有符号类型!强制转换 after 无符号溢出(很好且定义明确)为时已晚,你会得到有符号溢出,这是未定义的行为(环绕是 not 保证的,编译器会利用这个未定义的即使在二进制补码环绕很自然的平台上也有行为)。只需将size() 的结果转换为有符号类型并对其执行算术运算。
  • @MatteoItalia Afaik, (int)(unsigned)i == i 由较新的标准很好地定义。您能否为您的索赔提供一个标准参考?
  • 即使它是(标准参考?),这不是我们的情况 - 您不是在通过无符号值从/到有符号值进行往返,而是在计算溢出的无符号值然后将其转换为有符号值。这不能保证产生任何有用的东西(例如,它显然无法在具有符号和幅度或整数的补码表示的平台上正常工作)。
  • @MatteoItalia
  • Even roundtrip doesn't seem to be allowed, as I remembered。如果您修复了您谈论“转换回”为有符号值的句子,我会对此表示赞成-您无法真正以简单的方式将其转换回而不会溢出。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-17
  • 2011-11-13
  • 1970-01-01
  • 1970-01-01
  • 2012-07-01
  • 1970-01-01
相关资源
最近更新 更多