【问题标题】:why the type of `nil` is not `id` but `void *`为什么`nil`的类型不是`id`而是`void *`
【发布时间】:2013-06-15 10:40:22
【问题描述】:

在这段代码中

id (^block)(void) = ^(void) {
    return nil;
};

我有这个错误

使用“void *(^)(void)”类型的表达式初始化“id (^__strong)(void)”的不兼容块指针类型

所以我必须明确地将nil 转换为id 类型

id (^block)(void) = ^(void) {
    return (id)nil;
};

让编译器满意。购买为什么nil不是id类型?

对于这段代码

__typeof__(nil) dummy;
dummy = [NSObject new];

Objective-C 指针类型“NSObject *”到 C 指针类型“typeof (((void *)0))”(又名“void *”)的隐式转换需要桥接转换

也就是说nil 是(void *)0,但不只是与NULL 相同?我虽然nil 应该是(id)0 而Nil 应该是(Class)0?

我使用的是 Xcode 4.6.2

编译器:Apple LLVM 版本 4.2 (clang-425.0.28)(基于 LLVM 3.2svn)

【问题讨论】:

  • 您可以通过在 #import 语句下的前缀标题中添加以下内容来解决此问题:#undef nil #undef Nil #define nil ((id)(NULL)) #define Nil ((Class)(NULL))

标签: objective-c objective-c-blocks null


【解决方案1】:

您正在为块文字使用推断的返回类型,但您不必这样做。

消除该错误的正确方法是为块文字提供返回类型:

id (^block)(void) = ^id{
    return nil;
};

【讨论】:

    【解决方案2】:

    当一个块省略它的返回类型时,编译器的工作就是根据其主体中的返回来推断块的类型。但是,不幸的是,CLANG 会搜索其返回类型的完全腐烂的形式,这会导致奇怪的不一致。

    最容易理解的例子是对数组进行排序。比较器块的类型是NSComparisonResult(^)(id obj, id obj2),但如果你选择省略 NSComparisonResult 返回类型,编译器就会发牢骚:

    NSArray *sortedArray = [array sortedArrayUsingComparator: ^(id obj, id obj2) {
        if (//...) return NSOrderedAscending;
        return NSOrderedDescending;
    }];
    

    此块衰减为 int(^)(id obj, id obj2) 类型的块,编译器认为它不兼容(可以说,枚举只是命名为 int,因此应该编译)。

    以同样的方式,id 衰减为objc_object*,它不断衰减直到达到void*,或“任何通用指针”(根据 C 语言规范)。 void* 和 id 肯定是 not 同一类型。为了解决这个问题,你必须向编译器保证返回的类型是真实的,唯一的方法就是强制转换。

    LLVM 5.0 通过使编译器的推理更加智能来解决此问题。

    【讨论】:

      【解决方案3】:

      我不知道为什么 Apple 标头中的 nil 是 #define nil NULL(这是事实,但我不知道为什么它不是 (id)0 的原因),但我从来没有遇到过你的错误在最新版本的 Xcode 和编译器中提到。

      我想我记得早期版本的旧版编译器中存在一个错误,该错误会误解像块返回类型和所有内容中的隐式强制转换。

      您使用的是哪个编译器? LLVM-GCC 4.2?还是苹果 LLVM 4.2?较旧的编译器? 检查项目的构建设置。我建议切换到 Apple LLVM,并检查是否能解决您的问题。

      (事实上,LLVM-GCC 仅用于从旧 GCC 到新 LLVM 的过渡,因为现在有一些 Xcode 版本,但已弃用,将在下一个 Xcode 版本中删除)

      【讨论】:

      • 我使用的是 llvm 4.2。我在一个新创建的项目中测试代码,因此我的项目中没有遗留设置。请参阅我的编译器版本的更新问题。
      • 你在编译时使用的是哪个 SDK?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-11
      • 2019-03-17
      • 2013-04-26
      • 2014-04-09
      • 1970-01-01
      相关资源
      最近更新 更多