Is comparing a BOOL against YES dangerous?

后端 未结 4 2086
轻奢々
轻奢々 2020-12-15 12:29

I found a comment today in a source file:

//  - no longer compare BOOL against YES (dangerous!)

Is comparing BOOL against

相关标签:
4条回答
  • 2020-12-15 12:59

    All this is true, but there are valid counter arguments that might be considered:

    — Maybe we want to check a BOOL is actually YES or NO. Really, storing any other value than 0 or 1 in a BOOL is pretty incorrect. If it happens, isn't it more likely because of a bug somewhere else in the codebase, and isn't not explicitly checking against YES just masking this bug? I think this is way more likely than a sloppy programmer using BOOL in a non-standard way. So, I think I'd want my tests to fail if my BOOL isn't YES when I'm looking for truth.

    — I don't necessarily agree that "if (isWhatever)" is more readable especially when evaluating long, but otherwise readable, function calls,

    e.g. compare

    if ([myObj doThisBigThingWithName:@"Name" andDate:[NSDate now]]) {}
    

    with:

    if (![myObj doThisBigThingWithName:@"Name" andDate:[NSDate now]]) {}
    

    The first is comparing against true, the second against false and it's hard to tell the difference when quickly reading code, right?

    Compare this to:

    if ([myObj doThisBigThingWithName:@"Name" andDate:[NSDate now]] == YES) {}
    

    and

    if ([myObj doThisBigThingWithName:@"Name" andDate:[NSDate now]] == NO) {}
    

    …and isn't it much more readable?

    Again, I'm not saying one way is correct and the other's wrong, but there are some counterpoints.

    0 讨论(0)
  • 2020-12-15 12:59

    When the code uses a BOOL variable, it is supposed to use such variable as a boolean. The compiler doesn't check if a BOOL variable gets a different value, in the same way the compiler doesn't check if you initialize a variable passed to a method with a value taken between a set of constants.

    0 讨论(0)
  • 2020-12-15 13:15

    You should never compare booleans against anything in any of the C based languages. The right way to do it is to use either:

    if (b)
    

    or:

    if (!b)
    

    This makes your code much more readable (especially if you're using intelligently named variables and functions like isPrime(n) or childThreadHasFinished) and safe. The reason something like:

    if (b == TRUE)
    

    is not so safe is that there are actually a large number of values of b which will evaluate to true, and TRUE is only one of them.

    Consider the following:

    #define FALSE 0
    #define TRUE  1
    
    int flag = 7;
    if (flag)         printf ("number 1\n");
    if (flag == TRUE) printf ("number 2\n");
    

    You should get both those lines printed out if it were working as expected but you only get the first. That's because 7 is actually true if treated correctly (0 is false, everything else is true) but the explicit test for equality evaluates to false.

    Update:

    In response to your comment that you thought there'd be more to it than coder stupidity: yes, there is (but I still wouldn't discount coder stupidity as a good enough reason - defensive programming is always a good idea).

    I also mentioned readability, which is rather high on my list of desirable features in code.

    A condition should either be a comparison between objects or a flag (including boolean return values):

    if (a == b) ...
    if (c > d) ...
    if (strcmp (e, "Urk") == 0) ...
    if (isFinished) ...
    if (userPressedEsc (ch)) ...
    

    If you use (what I consider) an abomination like:

    if (isFinished == TRUE) ...
    

    where do you stop:

    if (isFinished == TRUE) ...
    if ((isFinished == TRUE) == TRUE) ...
    if (((isFinished == TRUE) == TRUE) == TRUE) ...
    

    and so on.

    The right way to do it for readability is to just use appropriately named flag variables.

    0 讨论(0)
  • 2020-12-15 13:19

    The problem is that BOOL is not a native type, but a typedef:

    typedef signed char      BOOL;
    
    #define YES             (BOOL)1
    #define NO              (BOOL)0
    

    As a char, its values aren't constrained to TRUE and FALSE. What happens with another value?

    BOOL b = 42;
    if (b)
    {
        // true
    }
    if (b != YES)
    {
        // also true
    }
    
    0 讨论(0)
提交回复
热议问题