Reputation: 4430
I found some code similar to the following:
BOOL hasValue_:1;
- (BOOL) hasValue {
return !!hasValue_;
}
- (void) setHasValue:(BOOL) value {
hasValue_ = !!value;
}
I'm wondering why the double exclamation points are necessary? Are we not already passing BOOL to the method and returning BOOL? Is BOOL really a typedef for an int?
Thanks!
EDIT
Thanks for all of the responses thus far. I understand that using !! with other data types effectively performs some typecasting to a boolean result. However, in the example above, I'm strictly working with BOOL already.
EDIT
If I'm working with a BOOL already, why is it necessary to normalize it to a 0 for false and 1 for true? Doesn't a BOOL guarantee that it is false for 0 and true for everything else?
Upvotes: 18
Views: 4715
Reputation: 104698
I'm wondering why the double exclamation points are necessary?
BOOL
is a signed char
, or a char
posing as a boolean type via typedef
. It will happily represent any integer in the range [SCHAR_MIN...SCHAR_MAX]
. The double exclamation point applies a boolean NOT operation twice, which effectively converts the original value to an int of 0 or 1, narrowing the value to the range of boolean.
But there's a twist: BOOL hasValue_:1;
declares a single-bit bitfield representation. It can represent two values. return !!hasValue_;
is not needed. However, it is needed to correctly narrow when going from signed char
(BOOL
) to one bit.
Are we not already passing BOOL to the method and returning BOOL?
Nope. It's a signed char
. !!value
reduces input values to YES
or NO
.
If I'm working with a BOOL already, why is it necessary to normalize it to a 0 for false and 1 for true?
Doesn't a BOOL guarantee that it is false for 0 and true for everything else?
BOOL
is a signed char
. A typedef
of signed char
does not make this guarantee.
C99 (which has been available for you to use for many years when targeting osx or ios) has a more useful boolean type representation (bool
). Unfortunately, BOOL
remains in regular use in objc for historical reasons. Personally, I use BOOL
only when necessary (e.g. overriding).
Upvotes: 13
Reputation: 14404
The double exclamation points is a way to cast an integer to a BOOL, where 1 (and ANY other value != 0) is true and 0 is false. Also, what you are writing is C and not objective-c. Your code will work in a C++ environment as well, since it is also a derivative of c.
Upvotes: 3
Reputation: 3516
... Some of its dialects, like C99 and Objective-C, provide standard definitions of a Boolean type as a synonym of int and macros for "false" and "true" as 0 and 1, respectively.
I think that the double negation ensures that the value of "true" is 1 (maybe to use it in arithmetic operations).
Upvotes: 2
Reputation: 57036
Looking at this question, BOOL is a typedef for signed char
. This means that it could have values aside from 0 or 1 (on all modern systems I'm familiar with, it can have values from -128 to 127). It shouldn't, but I wouldn't like to count on a BOOL always having values 0 or 1.
Therefore, it's desirable to have a way of normalizing it to 0 or 1. In C and the derived languages I'm familiar with, !
is the not operator, which takes a value and returns either 1 if the value is treated as false (in C, that would be numeric 0 or 0.0 or the null pointer constant for a pointer type), and 0 otherwise. !!
is just !
applied twice, which yields 0 for an initially false value and 1 for an initially true value.
Upvotes: 4
Reputation: 26094
It's the !
operator applied twice. The operator negates it's boolean argument.
So, what is the point of applying it twice, wouldn't you be back where you started? Not necessarily, as the type of the argument can be any type. This mean that you could have something like an integer i
and check if it's non-zero by !!i
. Also, this is often used to check if a pointer is non-NULL, for example:
bool doTrace = !!getenv("MY_TEST_VAR");
Upvotes: 2
Reputation: 57502
I'm not 100% certain about objective C, but in other languages, it's two boolean operators next to each other. It's typically used to ensure that falsy or trusy statements are converted to proper booleans (e.g. true or false). Since objective C is derived from C, there's a good chance that this is also what it's used for.
Upvotes: 4