35

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

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
A Person
  • 1,350
  • 12
  • 23
  • 2
    Also see [this](http://stackoverflow.com/questions/248693/double-negation-in-c-code), [this](http://stackoverflow.com/questions/206106/is-a-safe-way-to-convert-to-bool-in-c), [this](http://stackoverflow.com/questions/10406063/is-using-in-c-c-good-practice-and-is-it-common), and many more... – devnull Jan 04 '14 at 15:47
  • Oh man, sorry about that! – A Person Jan 05 '14 at 00:29
  • @Siidheesh it depends how you search, my initial searches did not turn them up either but slight modifications later on did. I personally don't find any of the dups to have hit the nail on the head they way the kernel newbies thread I found does so for that nugget it was probably worth it. Also Keith's explanation is also a far better explanation than most of the others in the dups as well, but he usually writes great answers in general. – Shafik Yaghmour Jan 05 '14 at 01:39
  • Yeah, searching for double negation did the trick – A Person Jan 05 '14 at 02:10

4 Answers4

33

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

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
6

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.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
4

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

Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
2

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

Lochlan
  • 2,666
  • 3
  • 23
  • 25