3

C ライクな言語では、演算子を使用せずにブール値を実行できることを理解していnotます: (C)

int myBool = TRUE;
myBool = !myBool;

しかし、私の質問は次のとおりです。これは舞台裏でどのように実装されていますか? 私の推測では、ジャンプを使用していますが、過度に使用すると非効率になる可能性があります: (Intel x86 構文)

; assume eax holds boolean
  test eax, eax
  jnz short boolTrue
  inc eax ; eax was 0, now 1
  jmp short after
boolTrue: ; eax non-zero
  xor eax, eax ; eax now 0
after:

示されているように、少なくとも 1 つのジャンプと 1 つのビット単位の 5 つの命令が必要ですand( test)。if (!!fileHandle)奇妙な理由で"double-nots" ( ) を実行するコード ベースを見たことがあるので、これを行うためのより簡単な方法が必要です。

だから(上記のように):コンパイラはx86でブール値をどのように処理しますか?!

4

4 に答える 4

4

分岐を必要としSETZない (set (if) zero (flag is set)) で実行できます。

于 2012-12-12T16:28:13.197 に答える
3

キャリーとブランチレス シーケンスを使用する可能性があります。

sub %eax, 1        ;; this produces carry only when %eax EQ zero
sbb %eax, %eax     ;; 0 when not carry, -1 when carry
and %eax, 1        ;; just get the least significant bit (also neg %eax will do)

eax=!eaxと_

sub %eax, 1        ;; 
sbb %eax, %eax     
add %eax, 1        ;; [-1, 0] + 1 == [0, 1]

のためにeax = !!eax

元の変数 (またはレジスタ eax) を無駄にしない一般的な算術演算を使用する命令シーケンスが 3 つ (またはそれ以下) あるかどうかはわかりませんでした。

于 2012-12-13T07:01:24.803 に答える
2

優れたコンパイラでは、NOT などの演算子を実装する方法は、通常、1 つのコード生成パターンに限定されません。コンパイラは、NOT 演算子が条件付きコンテキストで使用されているかどうか (たとえば、if ステートメントで使用されているか) にかかわらず、コンパイル時の最適化、NOT 演算子の直前のソースおよび/または生成されたコードなど、周囲のコンテキストの多くの要因を考慮します。値コンテキスト (代入で使用)。

if ステートメントで使用する場合、NOT 演算子は分岐を使用して実装される可能性が高くなります。値のコンテキストで使用する場合、NOT 演算子は結果の比較と取得 (分岐なし) を使用して実装される可能性が高くなります。

NOT 演算子がより大きな式で使用される場合、多くの場合、ネストされた演算子を逆にすることができます。そのため、見方によっては、NOT 演算子はコードをまったく生成しません。これは、a = ! (b > 0)またはのような式で発生する可能性がありif ( ! ( a && b ) )ます。を使用してもif ( !a )、おそらく a が実際には NOT されているのではなく、単に のようにテストされているだけであることがわかりますがif ( a )、分岐条件が逆になっています。

あなたが与える特定の例では、良いコンパイラの最善の努力(デバッグ用ではなく本番用のコードを生成する)を期待0myBoolていprintfます.

要するに、適切なコンパイラには、利用可能な多くの手法と、どれを使用するかを決定するための多くの基準があります。

于 2012-12-12T18:42:08.170 に答える
0

適切なブール値がある場合は、 を使用XORして 2 つの表現を切り替えることができます。には bool がないことに注意してくださいC。ゼロを false と解釈し、それ以外を true と解釈するだけです。C++どちらも適切なブール値をC#持っているため、ゼロ以外のチェックをいじる必要はなく、少なくともメソッドg++を使用しますXOR

于 2012-12-12T16:58:09.590 に答える