ObjC: if ( BOOL or boolean ) ?

Discussion in 'Mac Programming' started by zeppenwolf, Oct 6, 2014.

  1. zeppenwolf macrumors regular

    zeppenwolf

    Joined:
    Nov 17, 2009
    #1
    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.
     
  2. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #2
    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.
     
  3. subsonix, Oct 7, 2014
    Last edited: Oct 7, 2014

    subsonix macrumors 68040

    Joined:
    Feb 2, 2008
    #3
    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.
     
  4. subsonix macrumors 68040

    Joined:
    Feb 2, 2008
    #4
    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.
     
  5. mfram macrumors 65816

    Joined:
    Jan 23, 2010
    Location:
    San Diego, CA USA
    #5
    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.
     
  6. subsonix macrumors 68040

    Joined:
    Feb 2, 2008
    #6
    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);
    
     
  7. briloronmacrumo macrumors 6502

    briloronmacrumo

    Joined:
    Jan 25, 2008
    Location:
    USA
    #7
    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.

    No, and it isn't required.
    The 'if' statement shown evaluates for non-zero ( which effectively means a non-nil pointer in this case )
    Reminder: str is a pointer, so the "value" is actually an address and not the string data itself
     
  8. mfram, Oct 7, 2014
    Last edited: Oct 7, 2014
  9. mfram macrumors 65816

    Joined:
    Jan 23, 2010
    Location:
    San Diego, CA USA
    #9
    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.
     
  10. subsonix macrumors 68040

    Joined:
    Feb 2, 2008
    #10
    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.
     

Share This Page