136

かなり巨大なコード ベースのプロジェクトにたどり着きました。

私は主に C++ を扱っており、彼らが作成するコードの多くは、ブール論理に二重否定を使用しています。

 if (!!variable && (!!api.lookup("some-string"))) {
       do_some_stuff();
 }                                   

私は彼らが知的なプログラマーであることを知っています。

私は熟練した C++ の専門家ではありません。なぜ彼らがこれを行っているのかについての私の唯一の推測は、評価される値が実際のブール表現であることを完全に肯定したいということです。したがって、彼らはそれを否定し、それを再び否定して実際のブール値に戻します。

これは正しいですか、何か不足していますか?

4

14 に答える 14

132

boolに変換するのがコツです。

于 2008-10-29T22:47:07.023 に答える
75

実際、いくつかのコンテキストでは非常に便利なイディオムです。これらのマクロを取り上げます (Linux カーネルの例)。GCC の場合、次のように実装されます。

#define likely(cond)   (__builtin_expect(!!(cond), 1))
#define unlikely(cond) (__builtin_expect(!!(cond), 0))

なぜ彼らはこれをしなければならないのですか?GCC__builtin_expectはそのパラメーターを ではlongなくとして扱うboolため、何らかの形式の変換が必要です。それらのマクロを書いているとき、彼らは何が何であるかわからないので、単純にイディオムcondを使用するのが最も一般的です。!!

おそらく 0 と比較することで同じことを行うことができますが、私の意見では、二重否定を行う方が実際にはより簡単です。これは、C が持つキャストからブール値に最も近いからです。

このコードは C++ でも使用できます...これは最小公分母です。可能であれば、C と C++ の両方で機能することを行います。

于 2008-10-30T04:50:27.413 に答える
53

コーダーはオペランドを bool に変換すると考えていますが、&& のオペランドは既に暗黙的に bool に変換されているため、まったく冗長です。

于 2008-10-29T23:00:47.337 に答える
14

はい、それは正しいです。いいえ、何かが欠けているわけではありません。 !!boolへの変換です。詳細については、この質問を参照してください。

于 2008-10-29T22:49:55.130 に答える
12

これは、(変数 != 0) の書き込みを避けるための手法です。つまり、どんな型からでも bool に変換します。

このような IMO コードは、すぐに読めるコードではないため、メンテナンスが必要なシステムには適していません (したがって、最初に疑問が生じます)。

コードは読みやすくなければなりません。そうしないと、不必要に複雑なものを理解するのに時間がかかるため、時間の負債を将来に残すことになります。

于 2008-10-29T22:56:27.830 に答える
9

コンパイラの警告を回避します。これを試して:

int _tmain(int argc, _TCHAR* argv[])
{
    int foo = 5;
    bool bar = foo;
    bool baz = !!foo;
    return 0;
}

'bar' 行は、MSVC++ で「bool 'true' または 'false' への値の強制 (パフォーマンス警告)」を生成しますが、'baz' 行は問題なく通過します。

于 2008-10-31T10:56:39.420 に答える
6

従来の C 開発者にはブール型がなかったため、ブール型の比較に任意の数値データ型を頻繁に使用して#define TRUE 1いました。#define FALSE 0ができたのでbool、特定のタイプの割り当てと比較が数値型とブール型の混合を使用して行われると、多くのコンパイラが警告を発します。これら 2 つの使用法は、レガシー コードを操作するときに最終的に衝突します。

この問題を回避するために、一部の開発者は次のブール ID を使用してい!num_valueます。それ以外は。の場合に戻ります。それ以外は。に変換するには、単一の否定で十分です。ただし、ブール式の本来の意味を復元するには、二重否定が必要です。bool truenum_value == 0false!!num_valuebool falsenum_value == 0truenum_valuebool

このパターンはイディオムとして知られています。つまり、その言語に精通している人々が一般的に使用するものです。したがって、私はそれをアンチパターンとは見なしていませんstatic_cast<bool>(num_value)。キャストによって正しい結果が得られる可能性は十分にありますが、一部のコンパイラではパフォーマンスに関する警告が出力されるため、引き続き対処する必要があります。

これに対処するもう 1 つの方法は、次のように言うことです(num_value != FALSE)。私もそれで大丈夫ですが、全体として、!!num_valueはるかに冗長ではなく、より明確であり、2回目に見たときに混乱することはありません.

于 2014-12-03T00:13:20.457 に答える
4

オペレーターです!過負荷?
そうでない場合は、警告を生成せずに変数をブール値に変換するためにこれを行っている可能性があります。これは間違いなく標準的な方法ではありません。

于 2008-10-29T22:48:48.440 に答える
2

!!ブール型を持たない元の C++ に対処するために使用されました (C もそうではありませんでした)。


問題例:

内部if(condition)では、 はなどのconditionような型に評価する必要がありますが、まだ存在しないためそうではありません。double, int, void*bool

クラスint256(256 ビット整数) が存在し、すべての整数変換/キャストがオーバーロードされたとします。

int256 x = foo();
if (x) ...

x「真」またはゼロでないかどうかをテストするには、整数にif (x)変換してから、それがゼロでないかどうかを評価します。の典型的なオーバーロードは、 の最下位ビットのみを返します。 の最下位ビットのみをテストしていました。xint(int) xxif (x)x

しかし、C++ には!演算子があります。オーバーロード!xされた は通常、 のすべてのビットを評価しますx。したがって、反転されていないロジックに戻るためにif (!!x)使用されます。

参照C++ の古いバージョンは、if() ステートメントで条件を評価するときに、クラスの int 演算子を使用しましたか?

于 2014-08-25T23:14:12.823 に答える
1

変数がオブジェクト型の場合、! 演算子は定義されていますが、bool へのキャストはありません (さらに悪いことに、セマンティクスが異なる int への暗黙的なキャストです。! 演算子を 2 回呼び出すと、奇妙なケースでも機能する bool への変換が行われます。

于 2012-05-11T19:24:09.393 に答える
1

Marcinが述べたように、オペレーターのオーバーロードが有効かどうかは問題になる可能性があります。それ以外の場合、C/C++ では、次のいずれかを実行している場合を除いて問題ありません。

  • true(または C ではマクロのようなもの)と直接比較しTRUEますが、これはほとんど常に悪い考えです。例えば:

    if (api.lookup("some-string") == true) {...}

  • 何かを厳密な 0/1 値に変換したいだけです。C++ では、a への代入boolはこれを暗黙的に行います (暗黙的に に変換できるものに対してbool)。C で、または bool 以外の変数を扱っている場合、これは私が見たイディオムですが、私(some_variable != 0)自身は多様性を好みます。

より大きなブール式のコンテキストでは、物事が混乱するだけだと思います。

于 2008-10-29T23:08:24.077 に答える
0

多分プログラマーはこのようなことを考えていました...

!!myAnswer is boolean. In context, it should become boolean, but I just love to bang bang things to make sure, because once upon a time there was a mysterious bug that bit me, and bang bang, I killed it.

于 2008-10-29T23:31:08.960 に答える
0

それは正しいですが、C ではここでは無意味です。'if' と '&&' は、'!!' なしで式を同じように扱います。

C++ でこれを行う理由は、'&&' がオーバーロードされる可能性があるためだと思います。しかし、'!' もそうである可能性があるため、との型のコードを見ずに bool を取得できるとは限りませ。C++ の経験が豊富な人なら説明できるかもしれません。おそらくそれは、保証ではなく、多層防御の一種の手段として意図されています。variableapi.call

于 2008-10-29T23:02:55.133 に答える