使用if(1 || !Foo())是否有任何原因?

56

我阅读了一些旧代码:

if ( 1 || !Foo() )

有没有任何明显的原因不写成这样:

if ( !Foo() )

27
"1 || something()" 永远为真。因此,这两个语句不等价,但为什么要这样做,原因未知。 - SinisterMJ
10
if (1 || !foo()) 相当于 if (1) - devnull
为什么不直接删除条件语句呢?你说 1 || foo() 等同于 foo()。这意味着它们背后的代码是无用的。你可以将其与条件语句一起删除。 - Val
27
很可能这是暂时性的操作,目的是强制使条件为真(可能是一个 bug、解决方法或重构),并且没有被还原。使用源代码控制的 annotate/blame 功能找到这个改变的版本——你可能会得到一个有用的注释或 bug 数据库条目来帮助弄清楚为什么要进行更改。 - the_mandrill
2
可能Foo()的实现方式是 return rand() % 2; - Happy Green Kid Naps
1
1 && !Foo() 等于 !Foo() - Niklas R
4个回答

134

这两者并不是一样的。第一个示例由于1使得||短路, 因此永远不会运行Foo()函数。

为什么这么做呢?可能某人希望因调试目的而强制进入then分支,然后将其保留在那里。也可能是在没有源代码控制之前编写的,因此他们不想让代码丢失,只是暂时绕过它。


23
听起来像是在开发/调试期间插入的内容,之后因为有人忘了删除或害怕破坏某些东西而被保留下来。 - Medinoc
无论如何,这比注释掉要好得多,因为编译器会继续检查未激活的代码。出于调试原因,我经常这样做。 - usr
只有真正经验丰富的开发者才知道这个。+1 - Baby

44

if (1 || !Foo() )将永远被满足。由于短路评估!Foo()甚至不会执行。

当您想确保if下面的代码将被执行,但您不想删除其中的真正的条件(可能是为了调试),就会出现这种情况。

以下信息可能有助于您:

  • if(a && b) - 如果afalse,则不会检查b
  • if(a && b) - 如果atrue,则会检查b,因为如果它为false,表达式将为false
  • if(a || b) - 如果atrue,则不会检查b,因为这已经是true了。
  • if(a || b) - 如果afalse,则会检查b,因为如果btrue,则它将是true

强烈建议使用此目的的宏,如DEBUG_ON 1,这将使程序员的意图更容易理解,并且不会在代码中出现魔数(感谢@grigeshchauhan)。


6
如果条件语句为 if(1 || !Foo()) {code} ,那么它的意思和 if(1){code}{code} 是一样的。如果条件语句为 if(!Foo()),则根据 Foo() 的返回值,结果可能是 {code} 或者仅仅是 ; 。 :) - Grijesh Chauhan
我扩展了你的最后一个表达式...编辑:为了调试目的,可以使用宏“DEGUG_ON = 1”或注释掉它。if (DEGUG_ON || !Foo())(实际上我会注释掉代码)。;) - Grijesh Chauhan
“强烈建议为此目的编写一个宏,例如 DEBUG_ON 1”,当您试图找到该死的错误时,代码可读性通常是您最后考虑的事情 :-) - user541686
1
@Mehrdad 的确如此。但这个错误检查本身可能会变成一个错误。或者造成混淆,就像它对 OP 造成的那样 :D - Maroun

11
1 || condition

无论条件condition是否为真,true都是成立的。在这种情况下,condition甚至没有被求值。以下代码:
int c = 5;
if (1 || c++){}
printf("%d", c);

由于未增加 c ,因此输出结果为5。但是如果将1更改为0,则 c ++ 将被实际调用,使输出为6


通常的实际用途是在仅在很少满足计算结果为true的条件下才会调用的代码测试中使用:

if (1 || condition ) {
    // code I want to test
}

这样,条件将永远不会被评估,因此//我想测试的代码总是被调用。但这绝对不同于:
if (condition) { ...

这是一种语句,其中condition将会被评估(在你的情况下将调用Foo)。


“你不想等待直到那个条件被评估为真。” 是的,基本上短路是一种节省执行的技术! - Grijesh Chauhan
@GrijeshChauhan:我并没有提到性能,也没有提到执行时间。我指的是满足特定条件。 - LihO
哎呀,那是一种奇怪的语言特性。我一直认为只有具有副作用的代码才会被评估(所以基本上我认为非const方法和静态函数会被评估),但是我在一个简单的“hello world”中尝试了一下,在第一个情况下从未能够使条件得到评估 O_O - CoffeDeveloper

10

这个问题得到了适当的回答 - or操作符右侧被短路,表明这是一段调试代码,用于强制进入if块。但出于最佳实践的考虑(至少是我尝试的最佳实践),我建议提供以下替代方案,按推荐程度升序排列(最佳方案在最后):

注意:在编写示例后我注意到这是一个C++问题,示例是使用C#编写的。希望您可以进行翻译。如果有人需要,只需发布评论即可。

内联注释:

if (1 /*condition*/) //temporary debug

未在行内的评论:

//if(condition)
if(true) //temporary debug

名称指示函数

//in some general-use container
bool ForceConditionForDebug(bool forcedResult, string IgnoredResult)
{
      #if DEBUG
          Debug.WriteLine(
              string.Format(
                  "Conditional {0} forced to {1} for debug purposes",
                  IgnoredResult,
                  forcedResult));
          return forcedResult;
      #else
          #if ALLOW_DEBUG_CODE_IN_RELEASE
              return forcedResult;
          #else
              throw new ApplicationException("Debug code detected in release mode");
          #endif
      #endif
}

//Where used
if(ForceConditionForDebug(true, "condition"))...

//Our case
if(ForceConditionForDebug(true, "!Foo()"))...

如果您想要一个非常健壮的解决方案,可以向源代码控制添加存储库规则,以拒绝任何调用ForceConditionForDebug的检入代码。该代码不应以这种方式编写,因为它显然不能传达意图。它永远不应该被检入(或允许被检入)(源代码控制?同行评审?),并且在当前形式下绝对不应该被允许在生产中执行。


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