36

I reading this code, and have this line

 switch (!!up + !!left) {

what is !! operator ? two logical NOT ?

JuanPablo
  • 23,792
  • 39
  • 118
  • 164
  • Yup. Sounds like whoever wrote that didn't quite know what they were doing. – AndyG Apr 24 '12 at 23:13
  • 5
    Did you think to, you know, try it and find out? – Brian Roach Apr 24 '12 at 23:14
  • @Saucemaster, actually it's an idiom for mapping zero/nonzero to 0/1. It might also qualify as excessively clever in this particular use case (see "premature optimization"). – geekosaur Apr 24 '12 at 23:15
  • 3
    @SauceMaster: On the contrary. The double not trick is used very often. The Linux kernel source has some uses of it, and I'm pretty sure that the kernel hackers know what they are doing. – C2H5OH Apr 24 '12 at 23:15
  • 11
    It's the logical-yes operator. – James McNellis Apr 24 '12 at 23:25
  • @geekosaur and C2H50H: Thanks for the info, learn something new every day! – AndyG Apr 25 '12 at 01:06
  • I see no good reason why they didn't use `switch(up || left)` in this case, which is much more readable IMO? Does anyone else? – weston Apr 25 '12 at 09:24
  • 5
    @weston `(up || left)` will yield `0` or `1`, whereas `(!!up + !!left)` will yield `0`, `1`, or `2`. – kittemon Apr 27 '12 at 17:17
  • **SEE ALSO**: [What is “!!” in C?](https://stackoverflow.com/questions/14751973/what-is-in-c) – 0x90 Aug 03 '17 at 01:25

4 Answers4

57

yes, it's two nots.

!!a is 1 if a is non-zero and 0 if a is 0

You can think of !! as clamping, as it were, to {0,1}. I personally find the usage a bad attempt to appear fancy.

Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
  • 18
    not to be confused with a double knot, which is hard to get out of. – FlavorScape Apr 24 '12 at 23:14
  • 6
    It's not so much "clamping" as it is "normalizing". – kittemon Apr 24 '12 at 23:18
  • 9
    If you don't like it, what would you prefer? `(_Bool)` (or `(bool)` if `stdbool.h` has been included) works on C99 but it seems gratuitously dependent on C99, and I find a lot fewer people understand how cast-to-bool works than understand the `!!` idiom. The other alternative, `expr?1:0`, is just ugly and gratuitously verbose. – R.. GitHub STOP HELPING ICE Apr 25 '12 at 00:06
  • "a bad attempt to appear fancy" – Rob Apr 14 '20 at 18:43
14

You can imagine it like this:

!(!(a))

If you do it step by step, this make sense

result = !42;    //Result = 0
result = !(!42)  //Result = 1 because !0 = 1  

This will return 1 with any number (-42, 4.2f, etc.) but only with 0, this will happens

result = !0;    //Result = 1
result = !(!0)  //result = 0
Rodrigo
  • 11,909
  • 23
  • 68
  • 101
8

!! is a more-portable (pre-C99) alternative to (_Bool).

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
4

You're right. It's two nots. To see why one would do this, try this code:

#include <stdio.h>

int foo(const int a)
{
    return !!a;
}

int main()
{
    const int b = foo(7);
    printf(
        "The boolean value is %d, "
        "where 1 means true and 0 means false.\n",
        b
    );
    return 0;
}

It outputs The boolean value is 1, where 1 means true and 0 means false. If you drop the !!, though, it outputs The boolean value is 7, where 1 means true and 0 means false.

thb
  • 13,796
  • 3
  • 40
  • 68