web-dev-qa-db-ja.com

とは "!!" Cで?

次のスニペットに遭遇しました。

pt->aa[!!(ts->flags & MASK)] = -val;
  1. !!(二重の感嘆符/感嘆符/演算子ではない2つ)はcで何を表しますか?
  2. (!!NULL) == NULLではありませんか?
40
0x90

_!_は否定です。したがって、_!!_は否定の否定です。重要なのは、結果が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_になります。

62
Jan

ブール否定演算子!を繰り返し適用することにより、任意の値をints0または1に変換するために一般的に(ab)使用されます。

例:ブール値として表示すると56は「真」であるため、!56は0です。これは、!!56が1であるため、!0が1であることを意味します。

24
unwind

!EE == 0と同じであるため、!!E(E == 0) == 0と同じです。 !!は、ブール値を正規化するために使用されます。

7
ouah

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;

生成されたコードは確かに同一です。

4

数値を正規のブール値に変換します。

また、この場合、結果は配列のインデックス作成に使用されるため、これを行うことが重要であることに注意してください。

3
Hot Licks
  1. _!!x_は単なる!(!x)です。
  2. NULLが0として定義されている場合、!!NULL == !!0 == !(!0) == !(1) == 0
2

!!複数の式を使用した条件付きの割り当てなど、特定の状況でコンパイラを静めるための適切な方法です。例:

int _blah = 100;
int *blah;
if ( _blah > 100 && !!(blah = &_blah) ) {
// do stuff
}

私はこれをお勧めしません-警告は通常、適切なコーディング慣行を強制するためにあります。

1
SilentDirge