tags:

views:

1790

answers:

13

I just came onto a project with a pretty huge code base.

I'm mostly dealing with C++ and a lot of the code they write uses double negation for their boolean logic.

 if (!!variable && (!!api.lookup("some-string"))) {
       do_some_stuff();
 }

I know these guys are intelligent programmers, it's obvious they aren't doing this by accident.

I'm no seasoned C++ expert, my only guess at why they are doing this is that they want to make absolutely positive that the value being evaluated is the actual boolean representation. So they negate it, then negate that again to get it back to its actual boolean value.

Is this a correct? or am I missing something else?

Thanks, Brian Gianforcaro

+22  A: 

It's a trick to convert to bool.

Don Neufeld
Exactly right, it's a common idiom in most languages where ! is the negation operator with an implicit cast to boolean
Gareth
I think cast it explicitly with (bool) would be clearer, why use this tricky !!, because it is of less typing?
lz_prgmr
+2  A: 

Is operator! overloaded?
If not, they're probably doing this to convert the variable to a bool without producing a warning. This is definitely not a standard way of doing things.

Marcin
+9  A: 

Yes, it is a conversion to bool. See this question for more discussion.

jwfearn
+3  A: 

check here, already asked, Is !! a safe way to convert to bool in C++?

Comptrol
+3  A: 

Every time I see code like this it makes me want to scream NO, very loudly.

It's a trick to avoid writing (variable != 0), it saves a few bytes - should make no difference to the code generated by the compiler.

Code like this should be removed from systems because it requires understanding of a trick, and can cause doubt as to what is actually happening.

Code must be legible - otherwise you leave a time debt legacy for the future - as it takes time to understand something that is needlessly convoluted.

Richard Harrison
It's not a trick, it's simple typecasting.
orlandu63
My definition of a trick is something that not everyone can understand at the first reading. Something that needs figuring out is a trick.Also horrible because the ! operator could be overloaded...
Richard Harrison
+10  A: 

The coders think that it will convert the operand to bool, but because the operands of && are already implicitly converted to bool, it's utterly redundant.

fizzer
+1  A: 

It's correct but, in C, pointless here -- 'if' and '&&' would treat the expression the same way without the '!!'.

The reason to do this in C++, I suppose, is that '&&' could be overloaded. But then, so could '!', so it doesn't really guarantee you get a bool, without looking at the code for the types of variable and api.call. Maybe someone with more C++ experience could explain; perhaps it's meant as a defense-in-depth sort of measure, not a guarantee.

Darius Bacon
+1  A: 

As Marcin mentioned, it might well matter if operator overloading is in play. Otherwise, in C/C++ it doesn't matter except if you're doing one of the following things:

  • direct comparison to true (or in C something like a TRUE macro), which is almost always a bad idea. For example:

    if (api.lookup("some-string") == true) {...}

  • you simply want something converted to a strict 0/1 value. In C++ an assignment to a bool will do this implicitly (for those things that are implicitly convertible to bool). In C or if you're dealing with a non-bool variable, this is an idiom that I've seen, but I prefer the (some_variable != 0) variety myself.

I think in the context of a larger boolean expression it simply clutters things up.

Michael Burr
+1  A: 

Maybe the programmers were thinking something like this...

!!myAnswer is boolean. In context, it should become boolean, but I just love to bang bang things to make sure, because once upon a time there was a mysterious bug that bit me, and bang bang, I killed it.

dongilmore
+5  A: 

It's actually a very useful idiom in some contexts. Take these macros (example from the Linux kernel). For GCC, they're implemented as follows:

#define likely(cond)   (__builtin_expect(!!(cond), 1))
#define unlikely(cond) (__builtin_expect(!!(cond), 0))

Why do they have to do this? GCC's __builtin_expect treats its parameters as long and not bool, so there needs to be some form of conversion. Since they don't know what cond is when they're writing those macros, it is most general to simply use the !! idiom.

They could probably do the same thing by comparing against 0, but in my opinion, it's actually more straightforward to do the double-negation, since that's the closest to a cast-to-bool that C has.

This code can be used in C++ as well... it's a lowest-common-denominator thing. If possible, do what works in both C and C++.

Tom Barta
thank christ the right answer
Matt Joiner
+1  A: 

This topic has been discussed here.

Dima
+1  A: 

It side-steps a compiler warning. Try this:

int _tmain(int argc, _TCHAR* argv[])
{
    int foo = 5;
    bool bar = foo;
    bool baz = !!foo;
    return 0;
}

The 'bar' line generates a "forcing value to bool 'true' or 'false' (performance warning)" on MSVC++, but the 'baz' line sneaks through fine.

RobH
+1  A: 

Readability. It demonstrates a design pattern in a sense that you want to identify whether the value converted to a Boolean would be true or false.

Dr. Zim