【问题标题】:Why is nil preprocessed to ((void *)0) in Objective-C?为什么在 Objective-C 中将 nil 预处理为 ((void *)0)?
【发布时间】:2018-03-09 11:10:12
【问题描述】:

使用 Xcode 8.3.2,如果我在 Objective-C 文件中使用 nil 并选择 Product > Perform Action > Preprocess "MySourceFile.m",nil 将变为 ((void *)0)。我有几个问题:

  1. 如果nil 是语言的一部分,为什么预处理器要对它做任何事情?为什么编译步骤不直接接受nil
  2. nil 的全部要点是一个空的object 指针时,为什么nil 会变成((void *)0)?为什么不将其预处理为 ((id)0) 之类的东西,就像 this one 之类的来源定义的那样?

【问题讨论】:

  • 对于一个全新的项目是否如此?您在其中看到的项目是否包含一些奇怪的标题 #defines nil?或者构建定义这样一个宏的设置?

标签: objective-c xcode pointers clang c-preprocessor


【解决方案1】:

“语言的一部分”不一定意味着“编译器的一部分”。例如,C 标准强制 NULL 成为宏。没有 Objective-C 标准,所以 Objective-C 实现者可以做他们想做的事。重要的是,当您使用整个编程环境时,您可以访问一个nil 标记,该标记表示对象不存在。

nil 并不总是与 NULL 相同:它是 used to be defined as just 0,然后在 2007 年左右它是 changed to __DARWIN_NULL,在最近的版本中它将是 nullptr 在 Objective-C++ 模式和 @987654329 @ 否则。 (__DARWIN_NULL 来自<sys/_types.h>。)

Xcode 对于查找“伪关键字”的定义有点讨厌。我发现对于 Xcode 将其视为关键字的宏(如 nilNULL),找到它们的定义位置的最佳方法是重新定义它们并查看错误消息。

#define nil 0
        ^
foo/main.m:29:9: warning: 'nil' macro redefined [-Wmacro-redefined]

In module 'Foundation' imported from foo/main.m:9:
In module 'CoreFoundation' imported from /.../Frameworks/Foundation.framework/Headers/Foundation.h:6:
In module 'Dispatch' imported from /.../Frameworks/CoreFoundation.framework/Headers/CFStream.h:15:
In module 'os_object' imported from /.../include/dispatch/dispatch.h:66:
In module 'ObjectiveC' imported from /.../include/os/object.h:99:
/.../include/objc/objc.h:108:12: note: previous definition is here
#   define nil __DARWIN_NULL
           ^

【讨论】:

  • 这是很好的信息,谢谢。你对我的第二个问题有什么见解吗?
  • @Luke,我实在想不出任何理由,抱歉。 “Nil 是一个类,nil 是一个对象,而 NULL 是其他任何东西”是我过去曾争论过的事情,但我现在的观点是很难证明三个不同的常量具有相同的值,尤其是当任何一个它们可以适用于所有三个用例。需要指出的是,适当类型的 nil/Nil 可能有利于 Objective-C++ 中的模板参数推导,但仅此而已。没有人写 [nil objectAtIndex:0][Nil alloc]
【解决方案2】:
  1. nilNULL 都不是(Objective-)C 语言的一部分本身,也就是说它们不是关键字,而是库/框架中的预定义常量/宏。

  2. 这来自 C 标准:

值为 0 的整数常量表达式,或转换为 void * 类型的表达式称为 空指针常量。如果将空指针常量转换为指针类型,则生成的指针(称为 空指针)保证与指向任何对象或函数的指针不相等。

并且通常总是包含强制转换以明确结果是空指针常量。约定 C 指针类型使用NULL,Objective-C 对象引用类型使用nil,它们都扩展为空指针常量。

【讨论】:

    猜你喜欢
    • 2015-07-30
    • 1970-01-01
    • 1970-01-01
    • 2011-01-13
    • 2014-03-15
    • 1970-01-01
    • 2021-04-21
    • 2016-07-19
    • 1970-01-01
    相关资源
    最近更新 更多