Bil*_* VB 49 c lambda gcc anonymous-function
这个问题并不十分具体; 这真的是我自己的C浓缩,我希望其他人也能发现它有用.
免责声明:我知道很多人会有回应的冲动"如果你试图做FP然后只使用一种功能语言".我在一个需要链接到许多其他C库的嵌入式环境中工作,并且没有太多空间用于更多大型共享库,并且不支持许多语言运行时.而且,动态内存分配是不可能的.我也很好奇.
我们中的许多人已经看到了lambda表达式的这个漂亮的C宏:
#define lambda(return_type, function_body) \
({ \
return_type __fn__ function_body \
__fn__; \
})
Run Code Online (Sandbox Code Playgroud)
一个示例用法是:
int (*max)(int, int) = lambda (int, (int x, int y) { return x > y ? x : y; });
max(4, 5); // Example
Run Code Online (Sandbox Code Playgroud)
使用gcc -std=c89 -E test.c,lambda扩展为:
int (*max)(int, int) = ({ int __fn__ (int x, int y) { return x > y ? x : y; } __fn__; });
Run Code Online (Sandbox Code Playgroud)
所以,这些是我的问题:
线int(*X)究竟是什么?宣布?当然,int*X; 是指向整数的指针,但这两者有何不同?
看一下这个扩大的宏观,最终会__fn__做什么呢?如果我写一个测试函数void test() { printf("hello"); } test;- 立即抛出错误.我不明白那种语法.
这对调试意味着什么?(我打算尝试自己和gdb,但其他人的经验或意见会很棒).这会搞乱静态分析仪吗?
oua*_*uah 39
此声明(在块范围内):
int (*max)(int, int) =
({
int __fn__ (int x, int y) { return x > y ? x : y; }
__fn__;
});
Run Code Online (Sandbox Code Playgroud)
不是C而是有效的GNU C.
它使用了两个gcc扩展:
两个嵌套函数(限定的复合语句内的函数)和声明表达式(({}),基本上是产生一个值的块)用C不允许和来自GNU C.
在语句表达式中,最后一个表达式语句是构造的值.这就是嵌套函数__fn__在语句表达式末尾显示为表达式语句的原因.__fn__表达式中的函数指示符(在最后一个表达式语句中)通过常规转换转换为指向函数的指针.这是用于初始化函数指针的值max.
你的lambda宏利用了两个时髦的功能.首先,它使用嵌套函数来实际定义函数体(因此你的lambda实际上并不是匿名的,它只使用一个隐式__fn__变量(应该重命名为其他变量,因为双引导下划线名称是为编译器保留的,所以也许yourapp__fn__会有更好的事情).
所有这些本身都是在GCC复合声明中执行的(参见http://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html#Statement-Exprs),其基本格式如下:
({ ...; retval; })
Run Code Online (Sandbox Code Playgroud)
复合语句的最后一个语句是刚刚声明的函数的地址.现在,int (*max)(int,int)只需赋予复合语句的值,该语句现在是指向刚刚声明的"匿名"函数的指针.
调试宏当然是一种皇家的痛苦.
至于为什么test;..至少在这里,我得到'测试重新声明为不同类型的符号',我认为这意味着GCC将其视为声明而不是(无用)表达.因为无类型变量默认为int并且因为你已经声明test为函数(本质上void (*)(void)),所以你得到了......但我可能错了.
然而,任何想象力都无法携带.