使用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__; });
所以,这是我的问题:
-
什么行int(* X); 宣布? 当然, int * X; 是一个整数的指针,但这两者有什么不同呢?
-
看看这个已经实现的macros观,最后的
__fn__
做了什么? 如果我写一个testing函数void test() { printf("hello"); } test;
void test() { printf("hello"); } test;
– 立即抛出一个错误。 我不明白这个语法。 -
这对于debugging意味着什么? (我打算试试自己和gdb,但其他人的经验或意见将是伟大的)。 这会搞砸静态分析仪?
这个声明(在块范围):
int (*max)(int, int) = ({ int __fn__ (int x, int y) { return x > y ? x : y; } __fn__; });
不是C,而是GNU C.
它使用了两个gcc
扩展:
- 嵌套函数
- 语句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如此,这并不是任何想象力的延伸。
-
int (*max)(int, int)
是您声明的variables的types。 它被定义为一个名为max的函数指针,它返回int,并将两个int作为参数。 -
__fn__
是指函数名称,在这个例子中是max。 -
那里我没有答案。 我会想象如果你已经通过预处理器运行它,你可以通过它。
部分答案:它不是int(* X),你感兴趣的是int(* X)(y,z)。 这是一个函数指针,指向函数X,它取(y,z)并返回int。
为了debugging,这将是非常困难的。 大多数debugging器不能通过macros跟踪。 你很可能不得不debugging程序集。