24

I've been reading through the Linux kernel (specifically, 2.6.11). I came across the following definition:

#define unlikely(x)     __builtin_expect(!!(x), 0)

(from linux-2.6.11/include/linux/compiler.h:61 lxr link)

What does !! accomplish? Why not just use (x)?

See also:

Community
  • 1
  • 1
Willi Ballenthin
  • 6,444
  • 6
  • 38
  • 52
  • 1
    Dup: http://stackoverflow.com/questions/248693/double-negation-in-c-code and http://stackoverflow.com/questions/2168406/what-does-double-exclamation-point-mean – Joel Mar 26 '10 at 22:21
  • @Joel Potter, looks like you're right. I had searched for C rather than C++... – Willi Ballenthin Mar 26 '10 at 22:25
  • 2
    @Joel: those questions relate to C++ and Perl, respectively. While C++ is at least close, in practice the uses are at least somewhat different due to C having no built-in boolean type! – Shog9 Mar 26 '10 at 22:26
  • @Shog9, true. But that difference seems small in common usage. If nobody else agrees than this question will stay open. ;-) – Joel Mar 26 '10 at 22:37
  • 1
    This is the commit message that introduced the double negation: https://git.kernel.org/pub/scm/linux/kernel/git/tglx/history.git/commit/?id=2e0623e3e0d76e796aaa1ff2f7891bc7d43ebca2 – manlio Jul 01 '17 at 10:06

3 Answers3

34

!!(x) forces it to be either 0 or 1. 0 remains 0, but any non-zero value (which would be 'true' in a boolean context) becomes 1.

Spikatrix
  • 20,225
  • 7
  • 37
  • 83
Paul Tomblin
  • 179,021
  • 58
  • 319
  • 408
  • 6
    It's really not necessary in this case since we expect the result to be 0. It's really only necessary for the `#define likely(x) __builtin_expect(!!(x), 1)` to ensure that true is 1. It's likely only included in the `unlikely` definition for symmetry. – Chris Lutz Mar 26 '10 at 22:21
  • How interesting, I have previously used `x&&1` (or `x&&YES` in ObjC) for this. Never thought to use `!!`. – Nick Moore Mar 26 '10 at 23:09
11

It's not so much a language syntax but a common shorthand for converting a char or int into quasi-boolean.

In C logical operations such as == && ! and so on can act on int, char etc, as there is no boolean type, however according to the standard they are guaranteed to return 0 for False and 1 for true.

So for example if you have

int x = 5;

you can force it to convert to a "boolean" type (there is no boolean type in C hence the quotes) you do

x = !x; /* !5 which gives 0 always */
x = !x; /* which gives 1 always */
Rapptz
  • 20,807
  • 5
  • 72
  • 86
hhafez
  • 38,949
  • 39
  • 113
  • 143
  • In fact C does have a Boolean type. `_Bool` was introduced in C99, with a macro `bool` in `` expanding to `_Bool`. But the built-in logical operators like `==`, `&&`, `!`, et al still yield results of type `int` with the value `0` or `1`. – Keith Thompson Feb 20 '16 at 15:36
  • "however according to the standard they are guaranteed to return 0 for False and 1 for true." Are you sure? I thought any non-zero was true, which allows for compiler optimizations that return non-1 values to mean "true". – endolith Oct 26 '16 at 18:45
9

!!(x) is equivalent to (x) != 0 (unless some very oddball operator overloading is going on in C++).

The fact that it's not obvious what !!(x) is doing is a probably a good reason to use (x) != 0. Unless you want to be an elite kernel hacker.

See this closed question (if it's still around) for a discussion of the merits of !! (maybe that question will be be reopened, since this question indicates that it has some value).

Community
  • 1
  • 1
Michael Burr
  • 333,147
  • 50
  • 533
  • 760
  • 3
    It's "not obvious" what `!!(x)` does for half a second the first time you see it. After you see it and either a) think about it for a bit or b) ask someone else, you'll recognize what the `!!` "operator" does quite quickly. – Chris Lutz Mar 26 '10 at 22:33
  • 3
    @Chris - if it's a common idiom in your shop, it's probably OK to use it. On the other hand, I come across `!!(x)` infrequently enough that I have to pause for a moment to grok it. I don't have to cipher for a moment about what `(x) != 0` means. Not a huge deal, but I see little to recommend `!!(x)` over `(x) != 0`. – Michael Burr Mar 26 '10 at 22:45
  • 1
    Fair enough. I rather like the way it looks, but there isn't really a compelling argument for using it over `(x) != 0` (unless you need to rely on some objects overloading `!` to evaluate them in boolean contexts). – Chris Lutz Mar 26 '10 at 22:49