Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

zeppenwolf

macrumors regular
Original poster
Nov 17, 2009
129
3
Speaking specifically of Objc, (although it might apply other places), I understand that there can be a problem with casting a pointer to a BOOL:

Code:
BOOL CanMakeAStringB(void) {
    NSString* str = returnSomeValidStringOrReturnZero();
    return str;
}

Not very ObjC looking, sorry, but the point is that if an NSString* is cast to BOOL, then really there are 64 or at least 32 bits, I guess, being treated as a BOOL, an unsigned 8, so that, 1/256th of the time, theoretically, the pointer is some humongous value which just happens to have all 8 lowest bits equal to zero, so the BOOL is incorrectly determined to be false when it really should be true. In this case, it could be fixed by saying "return ( str != 0 );"

Am I correct so far? I think so; hope so.


So my question is, what happens in an "if" statement, or while, or ?: or...

Code:
NSString* str = returnSomeValidStringOrReturnZero();
if ( str ) praiseBob();

In the above code, in ObjC, does the compiler at some point cast the "str" to a BOOL type, in which case that code is buggy? Or does the compiler proceed directly to evaluate the zero or non-zero value of str, no matter how many bits, in which case it's fine?

IOW, in that code, is it necessary to change it to "if ( str != 0 )" ? I'm not asking about opinions about style, I mean is it really actually totally Turing-machine necessary?

Thx.
 
The condition of an if simply checks for 0 or non-zero, and treats them as false and true, respectively. All non-zero values have the same truth value (i.e. true).

For pointers (including all object pointers), nil or NULL are 0, and any non-nil value isn't.

The same rule applies for while statements, the conditional in a for, the conditional in a ?:, etc.

This is all identical to C, so you can look it up in any C reference or standard documentation.
 
For pointers (including all object pointers), nil or NULL are 0, and any non-nil value isn't.

NULL isn't required to be 0 actually, so if your testing if the pointer is NULL, just use NULL. Guess the same may be true for nil, but I'm too lazy to look it up now.


Edit: I'll add a disclaimer here. A while ago I was lambasted for suggesting this same thing (not here) pointing out that the NULL pointer constant is defined as (void*)0 according to the C standard, but then someone managed to dig up some ambiguity in the wording some place else in the standard related to NULL and managed to keep that separate from the NULL pointer constant. Not sure, but I think it's always the most safe option to not mix types, but explicitly test and assign say, a boolean to true/false (or YES/NO in case of BOOL), nothing else and you're safe no matter what. Same thing with NULL, why assign or test against 0, when there is NULL? Using NULL makes the intent explicit, it means and does one thing and nothing else.
 
Last edited:
Speaking specifically of Objc, (although it might apply other places), I understand that there can be a problem with casting a pointer to a BOOL:

Code:
BOOL CanMakeAStringB(void) {
    NSString* str = returnSomeValidStringOrReturnZero();
    return str;
}

I think another potential issue here is that BOOL is a type casted char, and thus can have 256 different values while a boolean can have 2. In C99 using stdbool.h the value is truncated to 0 or 1 (true/false). But using BOOL and then testing against YES may give a false negative since YES is 1.
 
For the O.P., one thing you might be confused about is the 'if' statement. An 'if' statement takes an expression, not a boolean. When the expression is non-zero, the next statement/block after the 'if' statement is taken. There's no casting to a boolean. The 'if' statement looks at the whole value of the expression, not just to lowest 8 bits.
 
The 'if' statement looks at the whole value of the expression, not just to lowest 8 bits.

I think the point was that a BOOL is a type casted char, so if the returned value has the lower 8 bits set to zero the result will be truncated to zero. The same as in a case like this:

Code:
unsigned char a = 512;
printf("%u\n", a);
 
Code:
BOOL CanMakeAStringB(void) {
    NSString* str = returnSomeValidStringOrReturnZero();
    return str;
}
As noted by other posters, there is no need to return a BOOL. Simply return an NSString and let the caller test it for non-nil. Of course in non-ARC you will need to consider string retention for the caller but that is another topic.

So my question is, what happens in an "if" statement, or while, or ?: or...
Code:
NSString* str = returnSomeValidStringOrReturnZero();
if ( str ) praiseBob();
In the above code, in ObjC, does the compiler at some point cast the "str" to a BOOL type
No, and it isn't required.
Or does the compiler proceed directly to evaluate the zero or non-zero value of str, no matter how many bits, in which case it's fine?
str is a pointer.
The 'if' statement shown evaluates for non-zero ( which effectively means a non-nil pointer in this case )
...Or does the compiler proceed directly to evaluate the zero or non-zero value of str
Reminder: str is a pointer, so the "value" is actually an address and not the string data itself
 
I think the point was that a BOOL is a type casted char, so if the returned value has the lower 8 bits set to zero the result will be truncated to zero. The same as in a case like this:

Code:
unsigned char a = 512;
printf("%u\n", a);

I suppose with that code casting to BOOL it would do the incorrect thing. But there's no reason for the code. It was built on an incorrect assumption.
 
I suppose with that code casting to BOOL it would do the incorrect thing. But there's no reason for the code. It was built on an incorrect assumption.

I agree, but that was the first example given where the low eight bits are mentioned. The other issue is that you would expect to be able to compare a BOOL to YES/NO, which you can't if you assign anything but YES/NO.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.