3

In Xcode 6.1.1 (Obj-C)

#if 1
    NSLog(@"print 1");
#endif

#if TRUE
    NSLog(@"print TRUE");
#endif

#if YES
    NSLog(@"print YES");
#endif

And the result:

print 1
print TRUE

Can explain to me the result ? Why #if TRUE vs #if YES vs #if 1 are different?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Dung Le
  • 33
  • 3
  • 1
    Hint: what is the difference between (`1`, `TRUE`) and `YES`? – Sourav Ghosh Jan 07 '15 at 07:50
  • since these are preprocessor commands and not objective-c, it does not use YES as true like objective-c does, its trying to use YES like a variable that is not defined i think – Fonix Jan 07 '15 at 07:51
  • @SouravGhosh: TRUE/FALSE is unsigned char, YES/NO is signed char. But why they are different in this situation ? – Dung Le Jan 07 '15 at 07:55
  • 1
    Oh no, again I got misunderstood. What i tried to point out is you should concentrate on _pre-processing_ state. there, `1` and `TRUE` are _defined_ [or known] having a `non-zero` value, `YES` is not defined _yet_. – Sourav Ghosh Jan 07 '15 at 07:59

4 Answers4

1

Mhm... I`m not really an objective-c person, I personally like c++ better, but let me try to answer you anyways.

if 1

The compiler, in the end of it, like pretty much everything in computers, runs on zeros and ones. When you write an "if 1" statement in your code, it will always do it, like every other number you might put there - that is, except zero. That's because the bit representation of 0 in bytes is "00000000", which represends a negative value. Because of that, the most basic statement you can make to make sure you have a true, in the code level and in the compiler level, is a if(nonzero number here) - which will always be true.

if TRUE

true is a saved word in the compiler, which in the end becomes a 1. That's why if(true) always works; naturally, i assume it takes some time for the compiler to parse it - but that's pretty much the only difference, and it's fairly minor.

if YES

The compiler does not know the word "Yes". Thus, it automatically assumes its a parameter, and tries to find if it was declared before. When it finds you didnt define it before on in your program, it puts the default value in the if statement - which is, false; Thus, the command is not executted.

Hope i helped :)

A. Abramov
  • 1,823
  • 17
  • 45
0

If the term YES is either not defined or defined as 0, then the #if will never become true.

If the identifier is not defined, it is treated as 0. So the preprocessor will see

#if 0
    NSLog(@"print YES");
#endif

Which will also not execute the NSLog command.

The code in the #if statement will only be executed when YES is

  1. defined and
  2. set to a non-zero value
eckes
  • 64,417
  • 29
  • 168
  • 201
  • wrong. An identifier that is not defined on a preprocessor level evalutates to `0` in all preprocessor evaluations. – Jens Gustedt Jan 07 '15 at 08:04
0

In preprocessor expressions for #if, all unknown idetifiers evaluate to 0. So it seems that in your case TRUE is defined to something non-0 and YES is either undefined or defined with value 0.

Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
0

It is difficult to believe when you think about it, but the C programming language had no boolean type until 1998. Programmers came up with their own solutions, and over time it became convention to use an int type with 0 for no. When a boolean was eventually added it was as a true first class boolean type. This means that it can only store the values 0 and 1.read more here

You can test this for yourself in objC with something like this.

bool foo = 55;
NSLog ((foo) ?  (@"foo, it is true") :(@"no, foo is false") ); //will log true..
NSLog (@"foo's int value", (int)foo ); // will log 1 

now bool does use a full 8 bits, its just (i think) that only the first (or last depending on your architecture / endian-ness ) is ever written to / read from..

Now ObjectiveC has been around a lot longer than 1998. So BOOL is actually older than bool ! This is why it was always defined as char. It is actually capable of storing values between -127 and 128. Again you can test this in Xcode

    BOOL bar = 55;
    NSLog ((bar) ?  (@"bar, it is true too!") :(@"no, bar neither") ); 
//will again log true..
    NSLog (@"bar's int value", (int)bar ); 
// will log 55 on 32bit builds but 1 on 64bit builds 

Yes but not always as you can see. In 64bit objC BOOL is defined as bool !

from objc.h

 #if !defined(OBJC_HIDE_64) && TARGET_OS_IPHONE && __LP64__
    typedef bool BOOL;
    #else
    typedef signed char BOOL; 
    // BOOL is explicitly signed so @encode(BOOL) == "c" rather than "C" 
    // even if -funsigned-char is used.
    #endif

Because of bool and BOOL's messy legacy in C and objC the truth is testing for YES or true is not always 100% reliable. Instead I recommend you test for !false or !NO . Sounds ridiculous right?

heres a little blog about it I found on big nerd ranch

PS i totally understand that you're talking compiler conditionals, but you did tag it objC :)

Jef
  • 4,728
  • 2
  • 25
  • 33