使用GCC语句expression式的匿名函数

这个问题并不十分具体, 这真的是为了我自己的C丰富,我希望别人也可以发现它有用。

免责声明:我知道很多人都会有这样的冲动:“如果你想做FP,那么就用一种function性语言”。 我在embedded式环境中工作,需要链接到许多其他C库,并没有太多的空间可用于更多的大型共享库,并且不支持许多语言运行时。 而且,dynamic内存分配是不可能的。 我也很好奇。

我们中的许多人都看过这个漂亮的Cmacros,用于lambdaexpression式:

#define lambda(return_type, function_body) \ ({ \ return_type __fn__ function_body \ __fn__; \ }) 

一个例子是:

 int (*max)(int, int) = lambda (int, (int x, int y) { return x > y ? x : y; }); max(4, 5); // Example 

使用gcc -std=c89 -E test.c ,lambda扩展为:

 int (*max)(int, int) = ({ int __fn__ (int x, int y) { return x > y ? x : y; } __fn__; }); 

所以,这是我的问题:

  1. 什么行int(* X); 宣布? 当然, int * X; 是一个整数的指针,但这两者有什么不同呢?

  2. 看看这个已经实现的macros观,最后的__fn__做了什么? 如果我写一个testing函数void test() { printf("hello"); } test; void test() { printf("hello"); } test; – 立即抛出一个错误。 我不明白这个语法。

  3. 这对于debugging意味着什么? (我打算试试自己和gdb,但其他人的经验或意见将是伟大的)。 这会搞砸静态分析仪?

这个声明(在块范围):

 int (*max)(int, int) = ({ int __fn__ (int x, int y) { return x > y ? x : y; } __fn__; }); 

不是C,而是GNU C.

它使用了两个gcc扩展:

  1. 嵌套函数
  2. 语句expression式

C中不允许嵌套函数 (在复合语句中定义一个函数)和语句expression式({}) ,基本上是产生一个值的块({}) ,并且来自GNU C.

在语句expression式中,最后一个expression式语句是构造的值。 这就是为什么嵌套函数__fn__在语句expression式结尾处作为expression式语句出现的原因。 expression式中的函数标识符(最后一个expression式语句中的__fn__ )通过常规的转换转换为指向函数的指针。 这是用来初始化函数指针max

你的lambdamacros利用了两个时髦的function。 首先它使用嵌套函数来实际定义你的函数体(所以你的lambda并不是真正的匿名函数,它只是使用一个隐式的__fn__variables(它应该被重命名为别的,因为编译器保留了双__fn__和下划线名) ,所以也许像yourapp__fn__会更好)。

所有这些都是在GCC复合语句中执行的(参见http://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html#Statement-Exprs ),其基本格式如下所示:

 ({ ...; retval; }) 

复合语句的最后一个语句是刚刚声明的函数的地址。 现在, int (*max)(int,int)只被赋值为复合语句的值,它现在是刚刚声明的“匿名”函数的指针。

debuggingmacros是一个皇室的痛苦,当然。

至于test;的原因test; ..至less在这里,我得到'testing重新宣布为不同types的符号',我认为这意味着海湾合作委员会将其视为一种声明而不是(无用的)expression。 因为无typesvariables默认为int ,因为你已经声明test为一个函数(本质上, void (*)(void) ),你得到的..但我可能是错误的。

尽pipe如此,这并不是任何想象力的延伸。

  1. int (*max)(int, int)是您声明的variables的types。 它被定义为一个名为max的函数指针,它返回int,并将两个int作为参数。

  2. __fn__是指函数名称,在这个例子中是max。

  3. 那里我没有答​​案。 我会想象如果你已经通过预处理器运行它,你可以通过它。

部分答案:它不是int(* X),你感兴趣的是int(* X)(y,z)。 这是一个函数指针,指向函数X,它取(y,z)并返回int。

为了debugging,这将是非常困难的。 大多数debugging器不能通过macros跟踪。 你很可能不得不debugging程序集。