Я обнаружил следующий фрагмент:
pt->aa[!!(ts->flags & MASK)] = -val;
- Что означает
!!
(двойные восклицательные знаки/восклицательные знаки/два не оператора) в c? - Не
(!!NULL) == NULL
?
Я обнаружил следующий фрагмент:
pt->aa[!!(ts->flags & MASK)] = -val;
!!
(двойные восклицательные знаки/восклицательные знаки/два не оператора) в c?(!!NULL) == NULL
? !
является отрицанием. Итак, !!
- отрицание отрицания. Важно то, что результатом будет int
.
!!x
, если x == 0
- !!0
, то есть !1
, то есть 0
.!!x
, если x != 0
- !!(!0)
, то есть !!1
, то есть !0
, то есть 1
. !!
обычно используется, если вы хотите преобразовать любое ненулевое значение в 1, будучи уверенным, что 0 остается 0.
И действительно, !!NULL == NULL
, так как !!NULL == !!0
и !!0 == !1
и, наконец, !1 == 0
.
Следовательно, в короткой части кода, которую вы указали, индекс массива будет либо 0
, если значение выражения в скобках NULL
, а 1
в противном случае.
Обычно (ab) используется для преобразования любого значения в int
0 или 1 путем повторного применения булевого оператора, !
.
Например: !56
равно 0, поскольку 56 является "истинным", если рассматривать его как логическое. Это означает, что !!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
}
Я не рекомендую этого - обычно предупреждают, чтобы обеспечить хорошую практику кодирования.