为什么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的答案。