Why is this program produces different result with `YES` and `true`?

回眸只為那壹抹淺笑 提交于 2021-02-17 02:06:14

问题


Here is the full program. Can you figure out its console output?

#import <Foundation/Foundation.h>

#define kEnv YES

#if kEnv
#define x @"abc"
#else
#define x @"xyz"
#endif


#define kVersion true

#if kVersion
#define y @"abc"
#else
#define y @"xyz"
#endif

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSLog(@"x: %@; y: %@", x, y);
        NSLog(@"%@", kEnv ? @"abc" : @"cba");
        NSLog(@"%@", kVersion ? @"abc" : @"cba");
    }
    return 0;
}

Before moving forward, you can copy & paste, run, and checkout the result yourself.


The output is:

x: xyz; y: abc
abc
abc

Can anyone explain the reason?


回答1:


YES gets defined as __objc_yes in <objc/objc.h>, and that is a compiler-level symbol, unknown to the preprocessor.

(/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/objc/objc.h on my machine.)

You can see the definition by doing

#define T(X) #X
#define S(X) T(X)
printf("YES is: \"%s\"\n", S(YES));

The C preprocessor is an interesting beast. :)

EDIT: Why does

#if __objc_yes

behave as if __objc_yes was false? Because __objc_yes is completely unknown to the preprocessor; it is known only to the compiler. This is from the manual to the GNU preprocessor, but I believe it reflects the standard, about what the expression after #if can contain:

[...] Identifiers that are not macros, which are all considered to be the number zero. [...]




回答2:


If you add

#define YES 1

at the beginning you'd get the output you expect. The reason is that YES definition is probably more complex than the way given here and that messes up the preprocessor. You can test that by e.g. changing your test to

#if YES

(and removing my definition of YES) and you'd get the same result as you did earlier. This just shows that, however YES is defined, it does not trigger the

#if YES

test.

PS

I think if you want to use constants e.g.

#if XXX

or

#if XXX > 5

you need to define XXX as a numerical value otherwise the preprocessor can not perform the evaluation properly. I'd suggest you stick to just checking definitions e.g. just use

#ifdef XXX

and when you need to use

#if

only use numerical constants, not any expressions.

FWIW as mentioned here https://en.wikipedia.org/wiki/C_preprocessor the preprocessor is quite limited - the reference discuss some of the limitations.



来源:https://stackoverflow.com/questions/65517700/why-is-this-program-produces-different-result-with-yes-and-true

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!