C++ 返回语句行为不符预期

4
我有以下的C++代码:

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

在这里,lineNum 是一个 intstartLineNum 是一个 intlines 是一个 std::vector<std::string>,而 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

这是怎么回事?我以前从未遇到过这种奇怪的情况。


3
变量有哪些类型?请创建一个最小、完整和可验证的示例来展示给我们。 - Some programmer dude
4
也许您在处理无符号算术方面遇到了问题。lines.size() 是 size_t 类型,startLineNum 是什么类型? - marcinj
1
@marcinj 做得好!那就是问题所在。 - Martin Bonner supports Monica
这些值会在调试器中显示。我将编辑我的问题,以便指定这些值的类型。 - user9284152
1
@KillzoneKid:不对。只有有符号类型才会发生溢出 UB。无符号类型必须进行包装。 - Bathsheba
显示剩余7条评论
2个回答

11

lines.size()很可能是一个无符号类型。(如果lines例如是std::vector, 那么它肯定是unsigned。)

因此,根据参数提升的规则和术语中的事实

startLineNum + lines.size() - 1;

从左到右分组后,它们都被转换为无符号类型。0 + 0 - 1 的结果是 std::numeric_limits<decltype(lines.size())>::max(),一个非常大的数字,很可能比 lineNum 要小。

经验法则:在使用无符号类型时永远不要使用负数,除非你确实知道自己在做什么。

针对你的情况,将问题重新陈述为

lineNum < startLineNum + lines.size()

1
我的猜测是:
lineNum <= startLineNum + lines.size() - 1;

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

改为

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

一切都应该正常。


1
甚至更好:lineNum < startLineNum + lines.size() - Martin Bonner supports Monica
顺便说一下,我认为 startLineNumlineNum 更可能是 int 类型,而整数字面量 1 明确是 int 类型。 - Martin Bonner supports Monica
没错,你说得对。虽然不太具有指导性,但有些人可能认为它只适用于-1。 - Demosthenes
我的猜测是startLineNum和lineNum的类型为std::size_t,当然1的类型为int,但这并不意味着差异是有符号的... - Demosthenes
然而,lines.size()是无符号的,因此RHS上的和与差也是无符号的。 - Demosthenes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接