“if([bool] == true)”是否需要比“if([bool])多一步”?

时间:2009-07-01 16:20:11

标签: optimization boolean

这是一个纯粹迂腐的问题,以满足自己的好奇心。

我倾向于在问题中使用后一个选项(所以:if (boolCheck) { ... }),而同事总是写前者(if (boolCheck == true) { ... })。我总是有点嘲笑他,并且从他第一次开始编程时,他总是把它解释为一种旧习惯。

但是今天我发现实际上写出整个== true部分实际上可能需要额外的处理步骤,因为任何带有==运算符的表达式都会被计算为布尔值。这是真的吗?

换句话说,据我所知,没有 == true行的选项可以松散地描述如下:

  1. 检查X
  2. 选项 == true行更像是:

    1. 如果X为真,则Y为真,否则为假
    2. 检查Y
    3. 我说错了吗?或者也许任何普通的编译器/解释器都会消除这种差异?或者我忽略了什么,而且根本没有什么区别?

      显然,在实际观察到的表现方面没有区别。就像我说的那样,我只是好奇。

      编辑:感谢所有实际发布编译结果的人,以说明两种方法之间的步骤是否不同。 (看起来,大部分时间,他们都是,虽然只是轻微的。)

      我只想重申,我询问什么是“正确”的方法。我知道很多人喜欢一个人而不是另一个人。我也理解,从逻辑上讲,两者是相同的。我很好奇,如果CPU执行的实际操作对于两种方法都完全相同;事实证明,大部分时间(显然它取决于语言,编译器等),它们不是。

14 个答案:

答案 0 :(得分:18)

我认为与真实的比较表明你的伴侣缺乏理解。 Bool应该被命名为避免这种情况(例如isAvaliableif (isAvailable) {...})。

答案 1 :(得分:16)

我希望通过任何半合半的编译器来优化差异。

(我刚用C#检查过,两种语法的编译代码完全相同。)

答案 2 :(得分:13)

编译器应该生成相同的代码。然而,与真实相比可以说更好,因为它更明确。一般来说,我不做明确的比较,但你不应该因为这样做而取笑他。

编辑:最容易辨别的方法是尝试。 MS编译器(cl.exe)在汇编中生成相同数量的步骤:

int _tmain(int argc, _TCHAR* argv[])
{
    bool test_me = true;

    if (test_me) {
004113C2  movzx       eax,byte ptr [test_me] 
004113C6  test        eax,eax 
004113C8  je          wmain+41h (4113E1h) 
        printf("test_me was true!");
    }

    if (test_me == true) {
004113E1  movzx       eax,byte ptr [test_me] 
004113E5  cmp         eax,1 
004113E8  jne         wmain+61h (411401h) 
        printf("still true!");
    }
    return 0;
}

此时问题是做测试而cmp有相同的成本吗?我的猜测是肯定的,尽管专家可能会指出差异。

实际结果是你不应该担心这一点。你可能有更大的性能鱼炒。

答案 3 :(得分:10)

重复问题(Should I use `!IsGood` or `IsGood == false`?)。这是我之前回答的指针:

  

具体测试技术   反对真或假是不好的做法   如果有问题的变量是真的   应该用作布尔值   (即使它的类型不是布尔值) -   特别是在C / C ++中。测试   真可以(也可能会)导致   微妙的错误。

有关详细信息,请参阅以下SO答案:

Should I use `!IsGood` or `IsGood == false`?

这是一个线程,详细说明为什么“== true”在更明确的细节中经常是错误的原因,包括Stroustrup的解释: https://qt-project.org/forums/viewthread/32642

答案 4 :(得分:4)

这是Python(2.6)反汇编:

>>> def check(x): return (bool(x) == True)

>>> import dis
>>> dis.dis(check)
  1           0 LOAD_GLOBAL              0 (bool)
              3 LOAD_FAST                0 (x)
              6 CALL_FUNCTION            1
              9 LOAD_GLOBAL              1 (True)
             12 COMPARE_OP               2 (==)
             15 RETURN_VALUE        
>>> def check2(x): return bool(x)

>>> dis.dis(check2)
  1           0 LOAD_GLOBAL              0 (bool)
              3 LOAD_FAST                0 (x)
              6 CALL_FUNCTION            1
              9 RETURN_VALUE        

我认为check未被优化的原因是由于Python是一种动态语言。这本身并不意味着Python使用了一个糟糕的编译器,但它可以在这里进行一些类型推断。也许它在创建.pyd文件时有所不同?

答案 5 :(得分:4)

根据我的经验if (flag==true)是不好的做法。

第一个论点是学术性的:

如果您有bool flag,则可以是truefalse

现在,表达式

(flag==true)

再次,truefalse - 它不再具有表现力,只有多余 - flag不能比现在更“真实”或“更虚假”。只有在不明显flag是布尔值的情况下才会“更加清晰” - 但是有一种标准方法可以修复适用于所有类型的方法:选择更好的名称

超越理性,以下将“更好”:

((flag==true)==true)

第二个论点是务实的,特定于平台的

C和早期的C ++实现没有真正的“bool”类型,因此标志有不同的约定,最常见的是非零是真的。 API返回基于整数的BOOL类型并不常见,但不强制返回值为0或1.

某些环境使用以下定义:

#define FALSE 0
#define TRUE (!FALSE)

祝你好运if ((1==1) == TRUE)

此外,一些平台使用不同的值 - 例如VB互操作的VARIANT_BOOLshortVARIANT_TRUE-1

使用这些定义混合库时,与true的显式比较很容易就是伪装成良好意图的错误。所以,不要。

答案 6 :(得分:2)

MSVC ++ 6.0编译器为这两种形式生成略有不同的代码:

4:        if ( ok ) {
00401033   mov         eax,dword ptr [ebp-8]
00401036   and         eax,0FFh
0040103B   test        eax,eax
0040103D   je          main+36h (00401046)
....
7:        if ( ok == true ) {
00401046   mov         ecx,dword ptr [ebp-8]
00401049   and         ecx,0FFh
0040104F   cmp         ecx,1
00401052   jne         main+4Bh (0040105b)

如果我能正确记住我的8086时序,那么以前的版本应该会稍快一些: - )

答案 7 :(得分:2)

这会涉及特定语言以及他们认为“真实”的价值观。以下是两个常见问题:JavaScriptPHP

这两种语言中的三重等于运算符确保您确实在检查布尔类型的真值。例如,在PHP中,if ($value)的检查可能与if ($value==true)if ($value===true)不同:

$f = true;
$z = 1;
$n = null;
$a = array(1,2);

print ($f)        ?'true':'false'; // true
print ($f==true)  ?'true':'false'; // true
print ($f===true) ?'true':'false'; // true
print "\n";
print ($z)        ?'true':'false'; // true
print ($z==true)  ?'true':'false'; // true
print ($z===true) ?'true':'false'; // false
print "\n";
print ($n)        ?'true':'false'; // false
print ($n==true)  ?'true':'false'; // false
print ($n===true) ?'true':'false'; // false
print "\n";
print ($a)        ?'true':'false'; // true
print ($a==true)  ?'true':'false'; // true
print ($a===true) ?'true':'false'; // false
print "\n";
print "\n";

我希望每天发言的语言会告诉我们如何看待这个问题。

答案 8 :(得分:2)

“boolCheck == true”语法可能有一些理由取决于您正在测试的变量的名称。

例如,如果变量名称为“state”,那么您可以拥有:

if (state) {
   ...
}

或者你可以

if (state == true) {
   ...
}

在这种情况下,我认为后一种形式更清晰,更明显。

另一个例子是像“启用”这样的变量,在这种情况下,第一种形式更清晰。

现在有一个名为“state”的布尔变量是不好的做法,但你可能无法控制它,在这种情况下,“== true”语法可以提高代码的可读性。

答案 9 :(得分:1)

这取决于编译器。两种情况都可能有优化。

答案 10 :(得分:1)

测试等于true会导致错误,至少在C中:在C中,'if'可以用于整数类型(不仅仅是布尔类型),并接受任何非 - 零价值;然而,符号“TRUE”是一个特定的非零值(例如1)。这对于位标志来说很重要:

if (flags & DCDBIT)
{
    //do something when the DCDBIT bit is set in the flags variable
}

所以给出这样的函数......

int isDcdSet()
{
    return (flags & DCDBIT);
}

...表达式“if(isDcdSet())”与“if(isDcdSet()== TRUE)”不同。

反正;我认为优化编译器应该优化任何差异(因为没有逻辑差异),假设它是一种具有真正布尔值(而不仅仅是整数)类型的语言。

答案 11 :(得分:0)

没有逻辑上的区别,假设没有内部类型转换,例如测试fstream。

ifstream fin;
...
if( ! fin)
...

答案 12 :(得分:0)

如果您正在使用可空的布尔值,则可能不一样。

示例:

Bool? myBool = true

if(myBool)  // This will not compile

if(myBool == true)  //this will compile

答案 13 :(得分:0)

恕我直言,使用if (boolCheck == true)形式是一个坏主意,原因很简单:如果你不小心输入一个'等于'符号而不是双(即if (boolCheck = true)),它将分配{ {1}}到true并且将始终返回true,这显然是一个错误。当然,大多数现代编译器在看到它时会显示警告(至少C#编译器会这样做),但许多开发人员只是忽略警告......

如果您想要明确,您应该更喜欢这种形式:boolCheck。这样可以避免意外分配变量,如果忘记'等于'符号,将导致编译错误。