Objective-C 块中的 BOOL 返回类型出现问题
我偶然发现了块中 BOOL
返回类型的一个奇怪问题。具有以下定义:
typedef BOOL (^BoolBlock)(void);
...此代码通过:
BoolBlock foo = ^{ return YES; };
...但是无法编译:
BoolBlock bar = ^{ return YES || NO; };
并显示以下错误消息:
不兼容的块指针类型 初始化“BoolBlock”(又名“BOOL (^)(void)') 带有类型表达式 'int (^)(void)'
我可以使用显式强制转换来解决问题,但是如果没有它,这是否应该工作?有更好的解决方案吗?
I stumbled over a curious problem with BOOL
return type in blocks. Having the following definition:
typedef BOOL (^BoolBlock)(void);
…this code passes:
BoolBlock foo = ^{ return YES; };
…but this fails to compile:
BoolBlock bar = ^{ return YES || NO; };
With the following error message:
Incompatible block pointer types
initializing 'BoolBlock' (aka 'BOOL
(^)(void)') with an expression of type
'int (^)(void)'
I can solve the issue using an explicit cast, but shouldn’t this work without it? Is there a better solution?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
||正如 Chuck 所说,运算符返回 int 类型。
或者
|| operator returns int type as Chuck said.
or
您可能认为
||
运算符适用于 Ruby 和 Python 等语言,它返回第一个为 true 的操作数。在 C 中,如果任一操作数为真,则返回 1,否则返回 0 — 这就是为什么它认为您返回的是整数。You're probably thinking the
||
operator works in languages like Ruby and Python, where it returns in the first operand that is truthy. In C, it returns 1 if either operand is truthy and 0 otherwise — that's why it thinks you're returning an integer.正如其他人所说,您收到错误的原因是
e0 ||无论
都会返回e0
和e1
的类型如何,e1int
。由于编译器根据return
语句推断块返回类型,因此您有一个返回int
的块,并且您尝试将其分配给块变量其块返回类型为BOOL
。我个人更喜欢这种语法:
为了避免错误,明确块返回类型是
BOOL
。右值是一个块文字,被理解为返回类型为BOOL
的块,并且编译器应用通常的 C 转换。至于为什么会发生这种情况,这是一个设计决策,尽管似乎没有明确记录。1块是一项新的语言功能。编译器设计者2决定他们应该对块有更严格的语义 - 即块指针类型的分配必须具有严格匹配的类型 - 并且他们在将块分配给块变量时强制执行这些更严格的语义无论右值是块指针还是块文字。
由于目前还没有涵盖 C 或 C++ 中的块的 ISO/IEC 标准,因此编译器设计者可以自由地做出这些决定。 Apple 已将块提交给 ISO/IEC JTC1/SC22/WG14 作为 WG14/N1370 和 WG14/N1451 并且,如果他们接受它,则此行为(或某些变体) )应标准化并记录在案。
1Clang的源代码确实有注释指出块指针的赋值比函数指针的赋值更严格。
2I'我亲自询问过他们这个问题。
As others have stated, the reason you’re getting the error is that
e0 || e1
returns anint
regardless of the types ofe0
ande1
. Since the compiler infers the block return type based upon thereturn
statement(s), you have a block that returnsint
and you’re trying to assign it to a block variable whose block return type isBOOL
.I personally prefer this syntax:
to avoid the error, making it clear that the block return type is
BOOL
. The rvalue, a block literal, is understood as a block whose return type isBOOL
and the compiler applies the usual C conversions.As to why this happens, it’s a design decision, although it doesn’t seem to be explicitly documented.1 Blocks are a new language feature. The compiler designers2 have decided that they should have tighter semantics on blocks — namely, the assignment of block pointer types must have strictly matching types — and they enforce these tighter semantics when assigning a block to a block variable regardless of the rvalue being a block pointer or a block literal.
Since there’s no ISO/IEC standard covering blocks in C or C++ yet, compiler designers are free to make these decisions. Apple have submitted blocks to ISO/IEC JTC1/SC22/WG14 as WG14/N1370 and WG14/N1451 and, if they accept it, this behaviour (or some variant of it) should be standardised and documented.
1Clang’s source code does have a comment stating that assignment of block pointers is more strict than assignment of function pointers.
2I’ve personally asked them about this.