问题
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?
回答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 :)
回答2:
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
.
回答3:
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
- defined and
- set to a non-zero value
回答4:
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 :)
来源:https://stackoverflow.com/questions/27814691/if-true-vs-if-yes-vs-if-1-are-different-in-objective-c