【问题标题】:#if TRUE vs #if YES vs #if 1 are different in Objective-C?#if TRUE vs #if YES vs #if 1 在Objective-C中不同吗?
【发布时间】:2015-01-07 07:48:27
【问题描述】:

在 Xcode 6.1.1 (Obj-C) 中

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

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

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

结果:

print 1
print TRUE

可以向我解释一下结果吗?为什么#if TRUE vs #if YES vs #if 1 不一样?

【问题讨论】:

  • 提示:(1, TRUE) 和YES有什么区别?
  • 因为这些是预处理器命令而不是objective-c,它不像objective-c那样使用YES,它试图像我认为未定义的变量一样使用YES
  • @SouravGhosh:TRUE/FALSE 是无符号字符,YES/NO 是有符号字符。但是为什么他们在这种情况下会有所不同呢?
  • 哦不,我又被误解了。我试图指出的是你应该专注于 pre-processing 状态。在那里,1TRUE定义 [或已知] 具有 non-zero 值,YES尚未定义

标签: objective-c c-preprocessor


【解决方案1】:

嗯...我不是一个真正的objective-c人,我个人更喜欢c++,但还是让我试着回答你。

如果为 1

最后,编译器就像计算机中的几乎所有东西一样,在零和一上运行。当您在代码中编写“if 1”语句时,它总是会这样做,就像您可能放在那里的所有其他数字一样——也就是说,除了零。这是因为 0 在字节中的位表示是“00000000”,它代表一个负值。 正因为如此,在代码级别和编译器级别,您可以做出的最基本的声明是 if(此处为非零数字)——这将永远是正确的。

如果为真

true 是编译器中保存的单词,最终变为 1。这就是 if(true) 始终有效的原因;自然,我认为编译器需要一些时间来解析它——但这几乎是唯一的区别,而且相当小。

如果是

编译器不知道“是”这个词。因此,它自动假定它是一个参数,并尝试查找它之前是否声明过。当它发现你之前没有在你的程序中定义它时,它会将默认值放在 if 语句中——即 false;因此,该命令不会被执行。

希望我能帮上忙:)

【讨论】:

  • C 和派生语言区分大小写,因此true 不是TRUEtrue 也不是 C 中的关键字(但在 C++ 中)
【解决方案2】:

#if 的预处理器表达式中,所有未知标识符的计算结果为0。因此,在您的情况下,TRUE 似乎被定义为非0 并且YES 要么未定义要么定义为值0

【讨论】:

  • 实际上,YES 被定义为 __objc_yes 而没有被定义:-)
【解决方案3】:

如果术语YES 未定义或定义为0,则#if 将永远不会变为真。

如果未定义标识符,则将其视为0。所以预处理器会看到

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

这也不会执行NSLog 命令。

#if 语句中的代码只有在YES 为时才会执行

  1. 定义
  2. 设置为非零值

【讨论】:

  • 错误。未在预处理器级别定义的标识符在所有预处理器评估中评估为0
  • @JensGustedt:感谢您的来信。更新了答案。
【解决方案4】:

想想就很难相信,但 C 编程语言直到 1998 年才具有布尔类型。程序员提出了自己的解决方案,随着时间的推移,使用 int 类型(0 表示否)已成为惯例。当最终添加布尔值时,它是真正的第一类布尔类型。这意味着它只能存储值 0 和 1。read more here

您可以在 objC 中使用类似这样的东西自行测试。

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 

现在 bool 确实使用了完整的 8 位,它只是(我认为)只有第一个(或最后一个,取决于您的架构/字节序)被写入/读取..

现在,ObjectiveC 的存在时间比 1998 年要长得多。所以 BOOL 实际上比 bool 更老! 这就是为什么它总是被定义为 char。它实际上能够存储 -127 到 128 之间的值。同样,您可以在 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 

是的,但并非总是如您所见。在 64bit objC 中 BOOL 被定义为 bool !

来自 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

由于 bool 和 BOOL 在 C 和 objC 中的混乱遗留问题,事实是测试 YES 或 true 并不总是 100% 可靠。相反,我建议您测试 !false 或 !NO 。听起来很荒谬吧?

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

PS 我完全理解你在谈论编译器条件,但你确实将它标记为 objC :)

【讨论】:

    猜你喜欢
    • 2013-12-23
    • 1970-01-01
    • 2017-01-03
    • 2016-08-31
    • 1970-01-01
    • 1970-01-01
    • 2015-09-10
    相关资源
    最近更新 更多