Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective-C块中的布尔返回类型有问题_Objective C_Objective C Blocks - Fatal编程技术网

Objective-C块中的布尔返回类型有问题

Objective-C块中的布尔返回类型有问题,objective-c,objective-c-blocks,Objective C,Objective C Blocks,我偶然发现了一个关于BOOL块中返回类型的奇怪问题。具有以下定义: typedef BOOL (^BoolBlock)(void); …此代码通过: BoolBlock foo = ^{ return YES; }; …但这无法编译: BoolBlock bar = ^{ return YES || NO; }; 显示以下错误消息: 不兼容的块指针类型 初始化“BoolBlock”(又名“BOOL”) 带类型表达式的(^)(void)“”) ‘int(^)(void)’ 我可以使用显式ca

我偶然发现了一个关于
BOOL
块中返回类型的奇怪问题。具有以下定义:

typedef BOOL (^BoolBlock)(void);
…此代码通过:

BoolBlock foo = ^{ return YES; };
…但这无法编译:

BoolBlock bar = ^{ return YES || NO; };
显示以下错误消息:

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


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

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

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

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


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

我个人更喜欢这种语法:

BoolBlock bar = ^BOOL { return YES || NO };
为避免错误,请明确块返回类型为
BOOL
。rvalue是一个块文字,它被理解为返回类型为
BOOL
的块,编译器应用通常的C转换

至于为什么会发生这种情况,这是一个设计决策,尽管它似乎没有明确的文档记录。1块是一种新的语言特性。编译器设计人员2已经决定,他们应该在块上具有更严格的语义-即,块指针类型的赋值必须具有严格匹配的类型-并且他们在将块赋值给块变量时强制执行这些更严格的语义,而不管右值是块指针还是块文字

<>因为在C或C++中没有覆盖ISO/IEC标准的标准,编译器设计者可以自由地做出这些决定。苹果已经向as提交了块,如果他们接受,这种行为(或它的一些变体)应该标准化并记录在案

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


2我个人问过他们这件事。

那么为什么像
-(BOOL)foo{返回YES | | NO;}
这样的东西会编译?换句话说,为什么整型和非整型之间的区别在块大小写中很重要,而在函数one中却不重要?@zoul:函数有一个显式的返回类型,因此int将隐式转换为BOOL。但是您创建的块没有显式的返回类型,因此它从return语句推断其返回类型(这是块所具有的特殊功能)。您返回一个int,因此它推断该块返回一个int。只有在完全推断出该块的类型后,编译器才会根据您分配给它的变量的类型检查该类型,因此您得到类型不匹配。谢谢,在块定义中声明返回类型会有所帮助,而且这是一个比在返回之前进行强制转换更好的解决方案。Clang对
^BOOL(){…}
很满意。谢谢!我在尝试使用时遇到了相同的问题…=BOOL^而不是…=^BOOL^BOOL{}有效吗?似乎是这样的,不要提及这样的符号。只有^void(void){}、^(void){}和^{}。@Kazuki建议说“具有空参数列表的闭包可以通过将其声明为(void)或完全忽略(void)来指定它。”@Kazuki感谢建议链接@我明白你的意思。我要说的是,目前的措辞模棱两可,目前,编译器是最终的“标准”(尽管这可能被视为一个bug)。谢谢你让我知道这一点!我没有注意到。
BoolBlock bar = ^BOOL { return YES || NO };