块 (C语言扩展)
块(blocks)是由LLVM提出的类似于lambda表达式的非标准C语言扩展,亦可以应用于Objective-C与C++中。它的语法类似于这些函数中的闭包,即由大括号包括的语句块。
苹果设计块的一个目的是使设计基于Grand Central Dispatch线程结构的程序更容易[1][2],但块是独立于这一构架的,它也可以在其它程序中以与普通语句块十分相似的方式应用。苹果已经在苹果修改版的GCC编译器以及Clang LLVM编译器前端中实现了这一特性;同时,LLVM计划,包括了支持块特性的运行时库。
与函数定义类似,块可以有参数,也可以在其内部声明私有变量。与普通的C函数定义不同,块可以使用其上文中定义的变量。一个块定义会产生一个不透明的值,该值同时包括了块内代码的引用和定义时栈内局部变量的快照(而非调用时)。块可以在定义后被调用,其行为与函数指针相同。块可以如同函数指针一般被赋值到变量中,作为函数的参数传递,但若块需要在其被定义的范围之外被使用时,程序员(或API)需要将该块用特别的运算符(Block_copy)标记。
在定义块之后,块内的代码可以在任何时间被调用,语法与调用函数相同。
示例
一个简单的计数器的例子:[3]
#include <stdio.h>
#include <Block.h>
typedef int (^IntBlock)();
IntBlock MakeCounter(int start, int increment) {
__block int i = start;
return Block_copy( ^ {
int ret = i;
i += increment;
return ret;
});
}
int main(void) {
IntBlock mycounter = MakeCounter(5, 2);
printf("First call: %d\n", mycounter());
printf("Second call: %d\n", mycounter());
printf("Third call: %d\n", mycounter());
/* 由于是复制的块,因此需要释放 */
Block_release(mycounter);
return 0;
}
/* Output:
First call: 5
Second call: 7
Third call: 9
*/
编译
Linux:
clang -fblocks blocks-test.c -lBlocksRuntime
与GCC嵌套函数的关系
块在外表上与GCC的C扩展语句块内的嵌套函数相似[4]。然而,嵌套函数与块不同,在退出当前语句块后就不能被调用了。
C语言标准
块特性已经被提交到C标准委员会,作为C1x标准的一系列提案[5][6]。
参见
参考资料
- ^ Apple Technical Brief on Grand Central Dispatch (页面存档备份,存于互联网档案馆), retrieved on June 9, 2009.
- ^ Mac OS X 10.6 Snow Leopard: the Ars Technica review: Blocks. [2010-09-15]. (原始内容存档于2010-09-04).
- ^ : Bengtsson, J. Programming with C Blocks on Apple Devices. [2010-09-15]. (原始内容存档于2017-11-15).
- ^ Nested Functions: Using the GNU Compiler Collection (GCC). [2010-09-15]. (原始内容存档于2010-08-21).
- ^ http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1370.pdf (页面存档备份,存于互联网档案馆) BLOCKS PROPOSAL, N1451
- ^ http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1451.pdf (页面存档备份,存于互联网档案馆) APPLE’S EXTENSIONS TO C, N1451
外部链接
- Clang Language Extensions: Blocks. LLVM Project. [2010-06-09]. (原始内容存档于2010-07-16).
- "compiler-rt" Blocks Runtime Library | Blocks Runtime. LLVM Project. [2011-03-25]. (原始内容存档于2009-07-06).