1

Just wondering - given that I have a typedef enum 'color' (and property of the same name) with a valid element 'blue', why is this ok:

 BOOL isBlue;

 if (color == blue){
     isBlue = YES;
 }

but this is not:

BOOL isBlue;

isBlue = (color == blue);

I've just started using enums so maybe i'm missing something simple?

Edit - as mentioned 'blue' is one of the valid elements of the enum, not a BOOL itself, i.e:

typedef enum { Blue, Red, Yellow } color;

and

@property color color;

Edit 2 - here's my actual code, as requested. I'm a bit confused by the contradictory comments/answers. Should I expect this to compile (it doesn't)?

.h

typedef enum { AddRecipes, ManageRecipes, RemoveRecipes } mode;

<snip>

@property mode mode;

.m

 @synthesize mode;

 <snip>

 BOOL modeIsAddRecipe = (mode == AddRecipes);

Edit 3 - for posterity I should mention that my error was trivial and unrelated. The discussion below proved enlightening though, many thanks.

Ben Packard
  • 26,102
  • 25
  • 102
  • 183
  • 1
    Both are perfectly valid and will compile without errors or warnings. What problem are you seeing? – Anurag Apr 22 '12 at 02:02
  • @Anurag If `BOOL` is an enum that permits the values `YES` and `NO`, then the second form won't compile. – Adam Liss Apr 22 '12 at 02:03
  • 2
    @AdamLiss - `BOOL` is a `typedef` for a `signed char`, and the values `YES` and `NO` are preprocessor definitions. See this related [answer](http://stackoverflow.com/questions/541289/objective-c-bool-vs-bool). I'm guessing that `color` is a variable of the enum type `Color`. – Anurag Apr 22 '12 at 02:08
  • @Anurag Thanks for the link. I just skimmed through the answers to that related question, and now my head hurts. What a mess! :-) Programming languages are supposed to become clearer and less error-prone as they evolve, not more complex and confusing. – Adam Liss Apr 22 '12 at 02:14
  • Please post the code where `blue` and `color` are defined. – Rob Keniger Apr 22 '12 at 02:36
  • If (color == blue) then it will return true rather than YES. isBlue = (color == blue) ? YES : NO; – Serguei Fedorov Apr 22 '12 at 02:40
  • I updated the question. @Anurag is correct, color is a variable of enum type Color. – Ben Packard Apr 22 '12 at 03:46
  • I also added my actual code. The error is a simple 'Expression expected'. I might be making some other rookie error on this one. – Ben Packard Apr 22 '12 at 04:00

3 Answers3

3

The BOOL is a simple typedef which is signed char (not to be confused with bool type)

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

It means BOOL value can be YES, NO or anything else. For example, if you try

BOOL testBool = 9;
NSLog(@"%d", testBool);

It will print 9. No compiler magic or runtime magic involved. This would have no problem at all until some programmer write some stupid boolean comparison like if (testBool == YES) instead of if (testBool).

tia
  • 9,518
  • 1
  • 30
  • 44
2

I'm guessing that BOOL is also an enum. The purpose of an enum is to enumerate the values that can be stored in a variable of that type.

So if your BOOL enum has the values YES and NO, then those are the only values that can be assigned to a BOOL. You can't assign any other values, even if they evaluate to the same numeric values as YES and NO.

The == operator returns 1 or 0 (or true or false, depending on the language). But the compiler won't allow you to assign any of those values to a BOOL, because none of them is YES or NO.

What you can do is use the ternary operator:

isBlue = (color == blue) ? YES : NO;

This evaluates the condition and returns YES if it's true or NO if it's false.

Adam Liss
  • 47,594
  • 12
  • 108
  • 150
  • 2
    Some trivia: note that you can, in fact, assign values different than 1 (true) and 0 (false) to a boolean variable, using pointer tricks. How these hacks are handled is language-specific (some languages may consider any value greater than 0 to be true, while others will only look at the least significant bit). But this is only of academic interest, if even. – Thomas Apr 22 '12 at 02:30
  • @Thomas: Good point - thanks for the clarification. The +1 is for appropriate use of "hacks" and "academic interest." Anyone who uses pointers to intentionally defeat type-checking or other compiler warnings on my team will be transferred immediately. :-) – Adam Liss Apr 22 '12 at 02:34
  • `BOOL` isn't an `enum`; it's a `typedef` for `signed char`. `YES` and `NO` are defined by macros to `(BOOL)1` and `(BOOL)0`, respectively. All three are in ``. – Peter Hosey Apr 22 '12 at 03:25
  • @Thomas: No such tricks are necessary for `BOOL`, since it's just a `signed char`. You can assign any valid `signed char` value directly to the variable. Only C99's `_Bool` (a.k.a. `bool` if stdbool.h gets its way) can only be assigned 0 or 1 without cheating. – Peter Hosey Apr 22 '12 at 03:36
  • As mentioned in the comments above, I was thrown because I can usually use something like BOOL isTrue = (1 == 1). Though maybe I shouldn't. – Ben Packard Apr 22 '12 at 03:52
1

As @tia already told you, BOOL is defined as signed char, and YES and NO are defined as (BOOL)1 and (BOOL)0, respectively.

It's for that reason that both code samples you show in your question will work just fine. In the latter snippet, the equality expression evaluates to either 1 or 0. You can freely assign these integer values to a BOOL (signed char) value.

The code will compile and run successfully, with neither an error nor a misbehavior.

If you're seeing something different, please edit your question to include your actual code and the error it produces, because the code you provided works just fine.

Edit (now that you've provided the actual code): I think it should work, but it currently doesn't (as of Xcode 4.3.1) because Clang is interpreting “mode” as the type mode, not the instance variable mode. If you rename the type to RecipeMode or change the expression to either explicitly reference the instance variable (self->mode) or use the property (self.mode), it compiles fine.

So, congratulations. You've actually (in my opinion) found a compiler bug! I suggest reporting it.

Peter Hosey
  • 95,783
  • 15
  • 211
  • 370
  • I added my non-compiliing code. The error is 'Expected expression'. – Ben Packard Apr 22 '12 at 03:58
  • Error found - something too small to mention. Thanks for provoking me to rummage in the knowledge it should work. – Ben Packard Apr 22 '12 at 04:11
  • Bug ID is 11296187. I actually realized that I hadn't declared an iVar, only the property, so just inserted self and moved on. But you're right, even with the iVar in place it doesn't compile. – Ben Packard Apr 22 '12 at 04:29
  • 1
    @BenPackard: `@synthesize` creates an ivar, so an instance variable named `mode` did exist. But the compiler nonetheless preferred the type name, and then rejected your code on the grounds that a type name can't go there. `self->mode` uses the instance variable explicitly and unambiguously, and because the property provides that ivar, it will work whether you declare an ivar yourself or not. – Peter Hosey Apr 22 '12 at 04:44