在Objective-C块中遇到BOOL返回类型的问题

时间:2011-05-09 08:26:09

标签: objective-c objective-c-blocks

我在块中遇到BOOL返回类型的奇怪问题。具有以下定义:

typedef BOOL (^BoolBlock)(void);

...此代码通过:

BoolBlock foo = ^{ return YES; };

...但是无法编译:

BoolBlock bar = ^{ return YES || NO; };

出现以下错误消息:

  

不兼容的块指针类型   初始化'BoolBlock'(又名'BOOL   (^)(void)')带有类型的表达式   'int(^)(void)'

我可以使用显式强制转换解决问题,但如果没有它,这不应该工作吗?有更好的解决方案吗?

3 个答案:

答案 0 :(得分:15)

||运算符返回int类型,如Chuck所说。

BoolBlock bar = ^{ return (BOOL)(YES || NO); };

BoolBlock bar = ^BOOL (void){ return YES || NO; };
BoolBlock bar = ^BOOL (){ return YES || NO; }; // warns in gcc, ok with clang

答案 1 :(得分:11)

你可能认为||运算符在Ruby和Python等语言中工作,它在第一个操作数中返回真正的操作。在C中,如果任一操作数为真,则返回1,否则返回0 - 这就是为什么它认为你正在返回一个整数。

答案 2 :(得分:5)

正如其他人所说,您收到错误的原因是e0 || e1会返回int,无论e0e1的类型如何。由于编译器根据return语句推断出块返回类型,因此您有一个返回int的块,并且您尝试将其分配给块返回类型为{的块变量。 {1}}。

我个人更喜欢这种语法:

BOOL

以避免错误,清楚地表明块返回类型为BoolBlock bar = ^BOOL { return YES || NO }; 。 rvalue(块文字)被理解为一个块,其返回类型为BOOL,编译器应用通常的C转换。

至于为什么会发生这种情况,这是一个设计决定,虽然它似乎没有明确记录。 1 块是一种新的语言功能。编译器设计者 2 已经决定它们应该在块上具有更严格的语义 - 即,块指针类型的分配必须具有严格匹配的类型 - 并且当将块分配给块变量时它们强制执行这些更严格的语义无论rvalue是块指针还是块文字。

由于目前还没有涵盖C或C ++中的块的ISO / IEC标准,编译器设计者可以自由地做出这些决定。 Apple已经ISO/IEC JTC1/SC22/WG14WG14/N1370WG14/N1451提交了阻止,如果他们接受,则应该标准化并记录此行为(或其中的某些变体)。

1 Clang的源代码确实有一条注释说明块指针的赋值比函数指针的赋值更严格。

2 我亲自问过他们。