This question already has an answer here:
-
!! c operator, is a two NOT?
4 answers
I have encountered the following snippet:
pt->aa[!!(ts->flags & MASK)] = -val;
- What does
!!
(double exclamation marks / exclamation points/ two not operators) stand for in c?
- Isn't
(!!NULL) == NULL
?
!
is negation. So !!
is negation of negation. What is important is the fact that the result will be an int
.
!!x
if x == 0
is !!0
, that is !1
, that is 0
.
!!x
if x != 0
is !!(!0)
, that is !!1
, that is !0
, that is 1
.
!!
is used commonly if you want to convert any non-zero value to 1 while being certain that 0 remains a 0.
And indeed, !!NULL == NULL
, since !!NULL == !!0
and !!0 == !1
and finally !1 == 0
.
Consequently, in the short piece of code you cited the array subscript will be either 0
if the value of the expression in parenthesis is NULL
, and 1
otherwise.
It is commonly (ab)used to convert any value into the int
s 0 or 1 by repeated application of the boolean not operator, !
.
For instance: !56
is 0, since 56 is "true" when viewed as a boolean. This means that !!56
is 1, since !0
is 1.
!E
is the same as E == 0
so !!E
is the same as (E == 0) == 0
. !!
is used to normalize booleans values.
In C99 you can replace it by
#include <stdbool.h>
pt->aa[(bool)(ts->flags & MASK)] = -val;
Of course if your code is to be portable to C89 then you'd be better off doing the !! trick or
pt->aa[(ts->flags & MASK)!=0] = -val;
or
pt->aa[(ts->flags & MASK)?1:0] = -val;
The generated code will be certainly identical.
It converts a number into a canonical Boolean.
And note that in this case it's critical to do so, since the result is being used to index an array.
!! is a decent way to quiet the compiler in certain situations such as assignment in a conditional with more than one expressions, e.g:
int _blah = 100;
int *blah;
if ( _blah > 100 && !!(blah = &_blah) ) {
// do stuff
}
I don't recommend this -- warnings are usually there to enforce good coding practice.