When is Objective-C implicitly coerced to BOOL?
I am reading Mike Ash's Objective-C hooks page and now I am paranoid about implicitly mutable variables like id
to BOOL
.
Suppose I have a "dangerous" pointer with the least significant bits zeroed out, so casting it to BOOL
will result in NO
, even if it points to a valid object. Let's call this "dangerous" pointer foo
.
How do simple if statements work? Does the if statement cause a foo
value BOOL
when evaluating a condition? Or is it cast into a purely logical one?
if( foo )
{
[myArray addObject:foo];
}
Does it work the same way in triple expressions?
// Does this break when foo is 'dangerous'?
self.titleLabel.hidden = foo ? YES : NO ;
Or will it be ternary only if I do this:
// I'm pretty sure it breaks now
self.titleLabel.hidden = ((BOOL)foo) ? YES : NO ;
It seems to me that I am missing something basic about logical operations in C and how they relate to BOOL
. Please help me enlighten.
source to share
When is Objective-C implicitly cast into BOOL?
Never, because this phrase is semantically incorrect. The listing is, by definition, explicit. What you are asking for is called "implicit type conversion" (coercion - thanks Josh!).
Also, strictly speaking, conventions in Objective-C are not special: they inherit from C. Thus, expressions, when necessary to evaluate as boolean, are not treated as BOOL
, but how int
.
// Does this break when foo is 'dangerous'?`
self.titleLabel.hidden = foo ? YES : NO;
No, it is not. (expr)
when used as a "boolean" expression is equivalent (expr != 0)
. There are no risks here.
// I'm pretty sure it breaks now
self.titleLabel.hidden = ((BOOL)foo) ? YES : NO;
Now this might break as it is BOOL
just typed on signed char
, which is 8 bits in iOS. Thus, if foo
which is a (32-bit) pointer is truncated to 8 bits, and the bottom 8 bits of the pointer are zero, but the pointer itself was not nil
, it would incorrectly report false. You don't want to make that unnecessary, ugly and dangerous throw. If you want to be more explicit, write
var = (obj != nil) ? valueOne : valueTwo;
instead.