【问题标题】:C++ return statement not behaving as expectedC++ return 语句未按预期运行
【发布时间】:2018-01-29 14:21:16
【问题描述】:

我有以下 C++ 代码:

return lineNum >= startLineNum
&& lineNum <= startLineNum + lines.size() - 1;

这里,lineNumintstartLineNumintlinesstd::vector&lt;std::string&gt;lines.size()size_t 类型。

lineNum 为2,startLineNum 为0,lines.size() 为0 时,代码返回true,即使false 是预期的。这些值就是调试器中显示的值。

即使在可能的情况下添加括号:

return ((lineNum >= startLineNum)
&& (lineNum <= (startLineNum + lines.size() - 1)));

代码仍然错误地返回true

当我将代码重构为这种形式时:

int start = startLineNum;
int end = startLineNum + lines.size() - 1;
return lineNum >= start && lineNum <= end;

它现在按预期返回false

这里发生了什么?我从来没有遇到过这种奇怪的事情。

【问题讨论】:

  • 你如何分辨这些值?您是在查看调试器中显示的值,还是事先将它们打印出来?
  • 变量有哪些类型?请创建一个Minimal, Complete, and Verifiable Example 向我们展示。
  • 也许你对无符号算术有疑问。 lines.size() 是 size_t 类型,startLineNum 是什么类型?
  • @marcinj 干得好!这就是问题所在。
  • @KillzoneKid:不。只有有符号类型有溢出 UB。无符号类型必须换行。

标签: c++ visual-c++ return


【解决方案1】:

lines.size() 很可能是一个无符号类型。 (如果linesstd::vector,例如它当然unsigned。)

所以由于参数提升的规则,以及

中的条款
startLineNum + lines.size() - 1;

从左到右分组,它们都被转换为unsigned类型。

这意味着0 + 0 - 1std::numeric_limits&lt;decltype(lines.size())&gt;::max() - 确实很大,而lineNum 很可能小于它。

经验法则:在处理无符号类型时切勿使用否定,除非您真的知道自己在做什么。

在您的情况下,将问题重述为

lineNum < startLineNum + lines.size()

【讨论】:

    【解决方案2】:

    我猜是这样的

    lineNum <= startLineNum + lines.size() - 1;
    

    都是无符号类型。 linenum 是 2,另外两个是 0,无符号算术中的 0-1 非常大(如果 4 字节超过 40 亿)。

    改为

    lineNum + 1 <= startLineNum + lines.size();
    

    一切都会好的。

    【讨论】:

    • 或者更好:lineNum &lt; startLineNum + lines.size().
    • 顺便说一下,我认为startLineNumlineNum 的类型更可能是int,而整数文字1 肯定是 输入int
    • 不错,不错。尽管指导性稍差,但有些人可能认为它仅适用于 -1。
    • 我的猜测是 startLineNum 和 lineNum 的类型为 std::size_t,当然 1 的类型为 int,但这并不意味着差异已签名...跨度>
    • 不过,lines.size() 是无符号的,RHS 上的总和和差也是如此。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-10
    • 1970-01-01
    相关资源
    最近更新 更多