Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why use !!(condition) instead of (condition)? [duplicate]

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)?

like image 490
A Person Avatar asked Jan 04 '14 03:01

A Person


4 Answers

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).

like image 79
Shafik Yaghmour Avatar answered Nov 14 '22 11:11

Shafik Yaghmour


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.

like image 40
Keith Thompson Avatar answered Nov 14 '22 13:11

Keith Thompson


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.).

like image 4
Elliott Frisch Avatar answered Nov 14 '22 11:11

Elliott Frisch


It casts to a boolean, which can sometimes be useful.

like image 2
Lochlan Avatar answered Nov 14 '22 12:11

Lochlan