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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.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_Cocoa_Objective C Blocks - Fatal编程技术网

为什么Objective-C块不像其他Objective-C对象那样通过指针处理?

为什么Objective-C块不像其他Objective-C对象那样通过指针处理?,objective-c,cocoa,objective-c-blocks,Objective C,Cocoa,Objective C Blocks,在使用块的代码中,经常会看到如下声明: typedef void(^Thunk)(void); Thunk block1 = ^{NSLog(@"%d %p",i, &i);}; 而不是 typedef void(^Thunk)(void); Thunk *block1 = ^{NSLog(@"%d %p",i, &i);}; 块似乎是唯一直接处理而不是通过指针处理的Objective-C对象。为什么会这样?它们不是常规对象吗?如果您查看,您将看到块是ObjC对象。 如果检查

在使用块的代码中,经常会看到如下声明:

typedef void(^Thunk)(void);
Thunk block1 = ^{NSLog(@"%d %p",i, &i);};
而不是

typedef void(^Thunk)(void);
Thunk *block1 = ^{NSLog(@"%d %p",i, &i);};
块似乎是唯一直接处理而不是通过指针处理的Objective-C对象。为什么会这样?它们不是常规对象吗?

如果您查看,您将看到块是ObjC对象。 如果检查堆栈块(如示例中所示),您将看到如下内容:

(lldb) po myBlock
<__NSStackBlock__: 0xbfffc940>
(lldb)采购订单myBlock
您会注意到在
\u Block\u copy()
\u Block\u release()
中使用
void*
参数


非点性只是编译器提供的语法糖分,可以保护您免受块的脏位的影响。

块是C扩展。可以在C中使用块(支持扩展)

苹果只是碰巧用ObjC类型实现了块


实现细节:块是少数几个可以使用clang在堆栈上分配的ObjC类型之一。通常,这不是一个选项,因为几乎每个API都希望
objc_对象
是一个支持引用计数的堆分配。

如果您想知道缺少的
*
:在您的示例中,您键入了隐藏语法的块。您也可以对其他对象执行此操作:

typedef NSNumber *Number;
Number foo = @42;
将块指定给实际指定指针的变量时


块有点像C数组:块文本是由编译器创建的结构。块变量是幕后的指针。

您没有“直接”处理块。你在间接地处理它

语法
void(^)(void)
声明指向块的指针。类型“block”没有语法;“指向块的指针”类型只有语法

从:

抽象声明器

int (^)(char, float)
描述对块的引用,该块在调用时采用两个参数,第一个为char类型,第二个为float类型,并返回int类型的值。引用的块是不透明数据,可能位于自动(堆栈)内存、全局内存或堆内存中

相关位为“描述对块的引用”


该规范并不完全一致,因为(例如)它引用了“具有块类型的变量”和“块变量声明”。但事实上,变量始终包含引用(指针)对于一个块,从不将块直接作为其值保存。

来自描述块语法的LLVM文档:具有块类型的变量是使用函数指针样式的符号来声明的,用^代替*.\u类型表达式扩展了C表达式解析,以适应块引用声明tes函数指针声明。typedef int(*pointerTofUnctionThatReturnsInThingWithCharArg)(char);pointerTofUnctionThatReturnsInThingWithCharArg函数指针;^PointerTofUnctionThatReturnsInThingWithCharArg(float x){return functionPointer;}我认为它们是指针,只是语法基于C奇怪的函数指针语法。@nielsbot错了。C的函数指针语法中肯定使用了星号:
void(*func)(void);
@RichardJ.RossIII-nielsbot可能意味着语法相似,至少我是这么理解的。是的,没错。指向函数“thePtr”的指针:
void(*thePtr)(…)
,因此指向块“theBlock”:
void(^theBlock)(…)
。因此,它已经是一个指针了,但没有使用“*”。另外,请参见Rob的答案。