web-dev-qa-db-ja.com

「if([bool] == true)」は「if([bool])」よりも1ステップ多く必要ですか?

これは、私自身の好奇心を満足させるための、純粋に衒学的な質問です。

私は質問で後者のオプションを使用する傾向がありますが(つまり、if (boolCheck) { ... })、同僚は常に前者を書き込みます(if (boolCheck == true) { ... })。私はいつも彼にそれについて少しからかいました、そして彼はいつも彼が最初にプログラミングを始めたときからそれを古い習慣として説明しました。

しかし、今日私は、== true演算子を含む式はブール値に評価されるため、実際に==部分全体を書き出すには処理のための追加の手順が必要になる場合があることに気付きました。これは本当ですか?

言い換えれば、私が理解しているように、オプションなし==真の線は次のように大まかに説明できます。

  1. Xを確認してください

オプションwith == true行は次のようになります。

  1. Xが真の場合はYを真、それ以外の場合は偽とします。
  2. Yを確認してください

私は正しいですか?それとも、通常のコンパイラ/インタプリタはこの違いをなくしますか?それとも私は何かを見落としていますか、そして本当に違いはまったくありませんか?

明らかに、実際に観察されたパフォーマンスに関しては違いはありません。私が言ったように、私はただ興味があります。

編集: 2つのアプローチ間で手順が異なるかどうかを説明するためにコンパイルされた結果を実際に投稿してくれたすべての人に感謝します。 (ほんのわずかではありますが、ほとんどの場合、そうであったようです。)

私はではなく「正しい」アプローチとは何かについて質問していたことを繰り返し述べたいと思います。多くの人がどちらか一方を好むことを理解しています。また、論理的には、この2つは同一であることも理解しています。 CPUによって実行されている実際の操作が、両方のメソッドでまったく同じであるかどうかだけが気になりました。結局のところ、多くの場合(明らかに、言語やコンパイラなどに依存します)、そうではありません。

28
Dan Tao

コンパイラは同じコードを生成する必要があります。ただし、trueと比較すると、より明確になるため、間違いなく優れています。一般的に私は明示的な比較をしませんが、あなたはそれをするために彼をからかうべきではありません。

編集:伝える最も簡単な方法は試してみることです。 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;
}

この時点での問題は、testとcmpのコストが同じかどうかです。専門家は違いを指摘できるかもしれませんが、私の推測はイエスです。

実際の結果は、これについて心配する必要はないということです。おそらく、はるかに大きなパフォーマンスの魚を揚げることができます。

13
i_am_jorf

真との比較は、あなたのパートナーによる理解の欠如を示していると思います。これを避けるために、本には名前を付ける必要があります(isAvaliableif (isAvailable) {...}など)。

18
rlbond

私は、その違いが、まともなコンパイラーによって最適化されることを期待しています。

(C#で確認したところ、コンパイルされたコードは両方の構文でまったく同じです。)

16
LukeH

重複する質問( `!IsGood`またはʻIsGood == false`を使用する必要がありますか? )。これが私の前の答えへのポインタです:

問題の変数が実際にブール値として使用されることになっている場合(その型がブール値でなくても)、特にC/C++では、特にtrueまたはfalseに対してテストする手法は悪い習慣です。真に対してテストすると、微妙なバグが発生する可能性があります(おそらくそうなるでしょう)。

詳細については、次のSO回答を参照してください。

`!IsGood`またはʻIsGood == false`を使用する必要がありますか?

これは、Stroustrupの説明を含め、「== true」がしばしばfalseである理由の背後にある理由を詳細に説明するスレッドです。 https://qt-project.org/forums/viewthread/32642

10
Michael Burr

私の経験では、if (flag==true)は悪い習慣です。

最初の引数はアカデミックです:

_bool flag_がある場合は、trueまたはfalseのいずれかです。

さて、式

_(flag==true)
_

繰り返しになりますが、trueまたはfalseです。これは表現力がなく、冗長であるだけです。flagは、これまで以上に「より真」または「より偽」になることはできません。 flagがブール値であることが明らかでない場合にのみ、「より明確」になります-しかし、すべてのタイプで機能するものを修正する標準的な方法があります:より良い名前を選択してください

これを理由を超えて拡張すると、次のことが「さらに良く」なります。

_((flag==true)==true)
_

2番目の引数は実用的でプラットフォーム固有です

Cおよび初期のC++実装には実際の「ブール」型がなかったため、フラグにはさまざまな規則があり、最も一般的なのはゼロ以外のすべてが真であるということです。 APIが整数ベースのBOOL型を返すことは珍しくありませんが、戻り値を0または1に強制することはありません。

一部の環境では、次の定義を使用します。

_#define FALSE 0
#define TRUE (!FALSE)
_

if ((1==1) == TRUE)で頑張ってください

さらに、一部のプラットフォームは異なる値を使用します-例: VB相互運用機能はshort、_VARIANT_BOOL_は_VARIANT_TRUE_の_-1_です。

これらの定義を使用してライブラリを混合する場合、trueとの明示的な比較は、善意を装ったエラーになりがちです。だから、しないでください。

4
peterchen

これが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ファイルが作成されるときに違いが生じる可能性がありますか?

4
Mark Rushakoff

MSVC++ 6.0コンパイラは、次の2つの形式に対してわずかに異なるコードを生成します。

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のタイミングを正しく覚えていれば、前のバージョンは非常にわずかに速いはずです:-)

2
anon

これは、特定の言語と、彼らが「真実の」価値と見なすものに入ります。一般的なものは2つあります: JavaScript[〜#〜] php [〜#〜]

これらの両方の言語のトリプル等号演算子は、ブール型の真理を実際にチェックしていることを保証します。たとえば、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";

毎日話す言語が、この質問をどのように見ているかを教えてくれることを期待しています。

2
artlung

テストしている変数の名前によっては、「boolCheck == true」構文に正当化がある場合があります。

たとえば、変数名が「state」の場合、次のいずれかになります。

if (state) {
   ...
}

またはあなたが持つことができます

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

この場合、後者の形式の方がより明確で明白だと思います。

別の例は、「有効」のような変数です。この場合、最初の形式がより明確になります。

「state」と呼ばれるブール変数を持つことは悪い習慣ですが、それを制御できない場合があります。その場合、「== true」構文によってコードの可読性が向上する可能性があります。

2
skaffman

Trueと等しいかどうかをテストすると、少なくともCではバグが発生する可能性があります。Cでは、「if」を整数型(ブール型だけでなく)で使用でき、any非ゼロ値を受け入れることができます。 ;ただし、記号「TRUE」は1つの特定のゼロ以外の値です(例: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)」と同じではありません。

とにかく;最適化コンパイラは、(整数だけでなく)真のブール型の言語であると仮定して、(論理的な違いがないため)違いを最適化する必要があると思います。

1
ChrisW

コンパイラによって異なります。どちらの場合も最適化される可能性があります。

1
Daniel A. White

Null許容ブール値を使用している場合は、同じではない可能性があります。

例:

Bool? myBool = true

if(myBool)  // This will not compile

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

単純な理由で、if (boolCheck == true)形式を使用することはお勧めできません。誤って二重ではなく単一の「等号」を入力した場合(つまり、if (boolCheck = true))、 trueからboolCheckになり、常にtrueが返されますが、これは明らかにバグです。もちろん、最近のほとんどのコンパイラーは、それを見ると警告を表示します(少なくとも、C#コンパイラーは表示します)が、多くの開発者は警告を無視します...

明示的にしたい場合は、次の形式を選択する必要があります:if (true == boolCheck)。これにより、変数が誤って割り当てられるのを防ぎ、「等号」を忘れるとコンパイルエラーが発生します。

0
Thomas Levesque

Fstreamのテストなど、内部型キャストが行われていないことを前提として、論理的な違いはありません。

ifstream fin;
...
if( ! fin)
...
0
Paul Nathan