Objective-C 块中的 BOOL 返回类型出现问题

发布于 2024-11-05 13:19:12 字数 460 浏览 1 评论 0原文

我偶然发现了块中 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

旧话新听 2024-11-12 13:19:12

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

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

|| operator returns int type as Chuck said.

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

or

BoolBlock bar = ^BOOL (void){ return YES || NO; };
BoolBlock bar = ^BOOL (){ return YES || NO; }; // warns in gcc, ok with clang
蓝梦月影 2024-11-12 13:19:12

您可能认为 || 运算符适用于 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.

世界等同你 2024-11-12 13:19:12

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

我个人更喜欢这种语法:

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

为了避免错误,明确块返回类型是BOOL。右值是一个块文字,被理解为返回类型为 BOOL 的块,并且编译器应用通常的 C 转换。

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

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

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

2I'我亲自询问过他们这个问题。

As others have stated, the reason you’re getting the error is that e0 || e1 returns an int regardless of the types of e0 and e1. Since the compiler infers the block return type based upon the return statement(s), you have a block that returns int and you’re trying to assign it to a block variable whose block return type is BOOL.

I personally prefer this syntax:

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

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 is BOOL 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文