I've seen code where people have used conditional clauses with two '!'s
#define check_bit(var, pos) (!!((var) & (1 << (pos))))
#define likely(x) __builtin_expect(!!(x),1)
#define unlikely(x) __builtin_expect(!!(x),0)
are some of the examples I could find.
Is there any advantage in using !!(condition)
over (condition)
?
Well if the variable you are applying !!
is not already a bool
(either zero or one) then it will normalize the value to either 0
or 1
.
With respect to __builtin_expect
this kernel newbies thread discusses the notation and one of the responses explains (emphasis mine):
The signature of __builtin_expect
http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html) is:
long __builtin_expect (long exp, long c)
Note that the exp parameter should be an integral expression, thus no pointers or floating point types there. The double negation handles the conversion from these types to integral expressions automatically. This way, you can simply write: likely(ptr) instead of likely(ptr != NULL).
For reference in C99 bool
macro expands to _Bool
, true
expands to 1
and false
expands to 0
. The details are given in the draft standard section 7.16
Boolean type and values .
Logical negation is covered in 6.5.3.3
Unary arithmetic operators in paragraph 5:
The result of the logical negation operator ! is 0 if the value of its operand compares unequal to 0, 1 if the value of its operand compares equal to 0. The result has type int. The expression !E is equivalent to (0==E).
The unary !
logical negation operator, applied to any scalar, yields the int
value 0
if its operand is non-zero, 1
if the operand is equal to zero. Quoting the standard:
The expression
!E
is equivalent to(0==E)
.
Applying !
twice to the same scalar value yields a result that's false if the value is false, true if the value is true -- but the result is normalized to 0
or 1
, respectively.
In most cases, this isn't necessary, since any scalar value can be used directly as a condition. But in some cases you actually need a 0
or 1
value.
In C99 or later, casting the expression to _Bool
(or to bool
if you have #include <stdbool.h>
behaves similarly and might be considered clearer. But (a) the result is of type _Bool
rather than int
, and (b) if you're using a pre-C99 compiler that doesn't support _Bool
and you've defined your own bool
type, it won't behave the same way as C99's _Bool
.
The biggest I can see, is that it will force (or normalize) the value into 1
or 0
(that is a boolean value) regardless of how the x
or var
expression expands (e.g. char
or double
or int
or etc.).
It casts to a boolean, which can sometimes be useful.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With