13

I'm looking over the diffs submitted to a project by another developer, and they have a lot of code that does !!<some BOOL value>. In fact, this seems to be their standard pattern for implementing boolean getters and setters. They've implemented their code like:

- (BOOL) hasId {
    return !!hasId_;
}
- (void) setHasId:(BOOL) value {
    hasId_ = !!value;
}

I've never seen this pattern before, and am wondering if there is any benefit in using it. Is the double-negation doing anything useful?

aroth
  • 54,026
  • 20
  • 135
  • 176
  • the only time I've seen that was for a class that didn't a straightforward way to cast to bool, so they couldn't do `if(myInstance)`, but it did overload the unary `!` operator, so they would do `if(!!myInstance)`. But in your case, I have no idea. – filipe Jul 12 '11 at 23:25
  • Looks like it's a ProtoBuf generated sources. – Richard Topchii May 03 '19 at 09:41

5 Answers5

12

The double boolean operator just makes sure that the value returned is either a 1 or a 0. That's all : )

citizen conn
  • 15,300
  • 3
  • 58
  • 80
  • 5
    …which prevents code like `obj.hasId = 42; if (obj.hasId == YES)` from failing the condition. Technically `YES` is (currently) mapped to 1 so the integer values are different. Conceptually, though, both 42 and `YES` represent a true boolean value. The double negation collapses that 42-assignment to a `YES`-assignment. –  Jul 12 '11 at 23:26
  • Thanks, I assumed it was probably something like that. But is it useful to do it that way/are any potential errors avoided? Like perhaps this prevents an unexpected error when doing a comparison in the form of `if (obj.hasId == YES)`? Though isn't such a comparison in poor style anyways? Edit: nevermind, Bavarious beat me to it. – aroth Jul 12 '11 at 23:29
  • True, but its actually helpful sometimes, to convert to 1 or 0, like SQLite saves boolean fields only in 1 or 0. – citizen conn Jul 12 '11 at 23:31
  • 7
    What @Bavarious said, but -- if being that defensive -- I'd at least make the damned thing readable; `return _boolVar ? YES : NO;` – bbum Jul 12 '11 at 23:45
3

! is a logical negation operator. So if setHasId: was passed, eg., 0x2 then the double negation would store 0x1.

Chris Devereux
  • 5,453
  • 1
  • 26
  • 32
1

It is equivalent to:

hasId_ = value ? 1 : 0;

It is useful in some cases because if you do this:

BOOL x = y & MY_FLAG;

You might get 0 if MY_FLAG is set, because the result gets truncated to the size of a BOOL (8 bits). This is unexpected. For the same reasons, people sometimes prefer that BOOL is either 0 or 1 (so bit operations work as expected). It is usually unnecessary.

In languages with a built-in bool type such as C (as of C99) and C++, converting an integer to bool does this automatically.

Dietrich Epp
  • 205,541
  • 37
  • 345
  • 415
0

It makes more sense in some other cases for example where you are returning BOOL but don't want to put an if statement in.

- (BOOL)isMyVarSet
{
    return !!myVar;
}

In this case I can't just return myVar because it's not a BOOL (this is a very contrived example - I can't dig out a decent one from my projects).

Paul.s
  • 38,494
  • 5
  • 70
  • 88
0

I've used this before and I believe:

if (!!myVar)

is equivalent to:

if (myVar != nil)

Basically, I use it to verify the value of SOMETHING.

I will admit... this is probably not the best practice or most-understood way to accomplish this goal.

mbm29414
  • 11,558
  • 6
  • 56
  • 87
  • The difference is: (myVar != nil) is quite obvious, while (!!myVar) stops you in your tracks, you have to think hard what it does, and then you have to think even harder to figure out whether whoever wrote it actually meant it. Best to express clearly what you mean. – gnasher729 Mar 27 '14 at 17:17
  • Completely agree! My answer is 3 years old, and I ABSOLUTELY wouldn't write !!var in any new code today! – mbm29414 Mar 27 '14 at 20:50