次のスニペットに遭遇しました。
pt->aa[!!(ts->flags & MASK)] = -val;
!!
(二重の感嘆符/感嘆符/演算子ではない2つ)はcで何を表しますか?(!!NULL) == NULL
ではありませんか?_!
_は否定です。したがって、_!!
_は否定の否定です。重要なのは、結果がint
になるという事実です。
!!x
_ _x == 0
_が_!!0
_の場合、つまり_!1
_、つまり_0
_の場合。!!x
_ _x != 0
_が!!(!0)
の場合、つまり_!!1
_、つまり_!0
_、つまり_1
_の場合。_!!
_は、0が0のままであることを確認しながら、ゼロ以外の値を1に変換する場合に一般的に使用されます。
そして確かに、_!!NULL == NULL
_、_!!NULL == !!0
_と_!!0 == !1
_、そして最後に_!1 == 0
_なので。
したがって、引用した短いコードでは、括弧内の式の値がNULL
の場合は配列の添え字は_0
_になり、それ以外の場合は_1
_になります。
ブール否定演算子!
を繰り返し適用することにより、任意の値をint
s0または1に変換するために一般的に(ab)使用されます。
例:ブール値として表示すると56は「真」であるため、!56
は0です。これは、!!56
が1であるため、!0
が1であることを意味します。
!E
はE == 0
と同じであるため、!!E
は(E == 0) == 0
と同じです。 !!
は、ブール値を正規化するために使用されます。
C99では、次のように置き換えることができます
#include <stdbool.h>
pt->aa[(bool)(ts->flags & MASK)] = -val;
もちろん、コードをC89に移植できるようにする場合は、実行したほうがよいでしょう。トリックまたは
pt->aa[(ts->flags & MASK)!=0] = -val;
または
pt->aa[(ts->flags & MASK)?1:0] = -val;
生成されたコードは確かに同一です。
数値を正規のブール値に変換します。
また、この場合、結果は配列のインデックス作成に使用されるため、これを行うことが重要であることに注意してください。
!!x
_は単なる!(!x)
です。NULL
が0として定義されている場合、!!NULL == !!0 == !(!0) == !(1) == 0
。!!複数の式を使用した条件付きの割り当てなど、特定の状況でコンパイラを静めるための適切な方法です。例:
int _blah = 100;
int *blah;
if ( _blah > 100 && !!(blah = &_blah) ) {
// do stuff
}
私はこれをお勧めしません-警告は通常、適切なコーディング慣行を強制するためにあります。