私は2つの操作を混同しています:
if(!is_active)
{
do something here...
}
と
if(is_active == false)
{
do something here...
}
どれが他より速いですか?速い場合は、なぜ速いのか。0 と 1 のビット演算子で説明できますか。
私は2つの操作を混同しています:
if(!is_active)
{
do something here...
}
と
if(is_active == false)
{
do something here...
}
どれが他より速いですか?速い場合は、なぜ速いのか。0 と 1 のビット演算子で説明できますか。
コンパイルすると、同じマシン コードが生成されます。それは単なる構文の問題です。
標準(5.3.1)から:
論理否定演算子のオペランド ! 暗黙的に bool に変換されます (節 4)。変換されたオペランドが false の場合、その値は true になり、それ以外の場合は false になります。結果の型は bool です。
どちらも同等です。-S
アセンブラ出力を に生成する オプションを使用して、これを自分でテストできますfile.s
。amd64 で gcc を使用すると、たとえば次のようになります。
ファイル.cpp:
void f()
{
bool is_active = false;
if(!is_active) { dosomething(); }
if(is_active == false) { dosomething(); }
}
ファイル:
...
movzbl -1(%rbp), %eax
xorl $1, %eax
testb %al, %al
je .L3
call _Z11dosomethingv
.L3:
movzbl -1(%rbp), %eax
xorl $1, %eax
testb %al, %al
je .L2
call _Z11dosomethingv
.L2:
...
両方のインスタンスのコードが同じであることは簡単にわかります。
コンパイラーの最適化を含む Charles Bailey のコメントを更新-O2
ファイル.cpp:
extern bool is_active;
void f()
{
if(!is_active) { dosomething(); }
}
void g()
{
if(is_active == false) { dosomething(); }
}
ファイル:
cmpb $0, is_active(%rip)
je .L4
rep
ret
.p2align 4,,10
.p2align 3
.L4:
jmp _Z11dosomethingv
...
cmpb $0, is_active(%rip)
je .L7
rep
ret
.p2align 4,,10
.p2align 3
.L7:
jmp _Z11dosomethingv
if
今回は生成されるアセンブラ コードが異なりますが、やはり両方のステートメントで同じです。
コンパイラがまったく同じになるように最適化しない場合、本当にばかげたコンパイラになります。
しかし、そのうちの 1 つがより高速である場合は、との代わりに ASM コマンドif(!is_active)
が 1 つしか必要ないためです。INV
LOAD
CMP
自分で試すよりも簡単な方法はありません:)両方を使用して時間を測定する簡単なプログラムを作成します。コンパイラと最適化に固有のものである可能性があると思います。
ただし...このコードを最適化しようとしても無駄です...間違った最適化に焦点を合わせています:)
最適化されていない場合、最初は否定であり、その後にゼロとの比較が続きます。2 番目は、ゼロとの比較が続く比較です。
最適化すると、それらはほぼ確実に同じになります。
この質問に対する答えは、コンパイラがコードを理解する能力 (コンパイル テンプレート) に大きく依存します。基本的に、あなたは同じバイナリの質問をしています - 変数 is_active は 0 ですか? それでも、あなたは2つの異なる方法でそれを求めています:
スマート コンパイラ (およびサポートするアセンブリ ISA) は、論理否定を実行してから 0 と比較するのではなく、最初から 0 に等しくない値と比較します。
簡単に言うと、コンパイラがセミインテリジェントであり、ISA が 0 以外の値との比較をサポートしていると仮定します。まったく同じはずです
次のように書くのは悪い習慣です。
if(is_active == false)
これをしないでください。
そして、そのような操作の速度について...私たちは2013年です.;-)