这个问题并不十分具体; 这真的是我自己的C浓缩,我希望其他人也能发现它有用。
免责声明:我知道很多人会有回应的冲动,“如果你试图做FP然后只使用一种功能语言”。我在一个需要链接到许多其他C库的嵌入式环境中工作,并且没有太多空间用于更多大型共享库,并且不支持许多语言运行时。而且,动态内存分配是不可能的。我也很好奇。
我们中的许多人已经看到了lambda表达式的这个漂亮的C宏:
#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; 是一个指向整数的指针,但这两者有何区别?
看一下exapnded macro,最终的__fn__
到底是做什么的?如果我编写一个测试函数void test() { printf("hello"); } test;
- 会立即抛出错误。我不明白这种语法。
这对调试意味着什么? (我打算尝试自己和gdb,但其他人的经验或意见会很棒)。这会搞乱静态分析仪吗?
答案 0 :(得分:38)
此声明(在块范围内):
int (*max)(int, int) =
({
int __fn__ (int x, int y) { return x > y ? x : y; }
__fn__;
});
不是C,但是有效的GNU C.
它使用了两个gcc
扩展程序:
不允许嵌套函数(在复合语句中定义函数)和语句表达式(({})
,基本上是一个产生值的块)在C中来自GNU C。
在语句表达式中,最后一个表达式语句是构造的值。这就是嵌套函数__fn__
在语句表达式末尾作为表达式语句出现的原因。表达式中的函数指示符(最后一个表达式语句中的__fn__
)通过常规转换转换为指向函数的指针。这是用于初始化函数指针max
的值。
答案 1 :(得分:6)
你的lambda宏利用了两个时髦的功能。首先它使用嵌套函数实际定义函数体(所以你的lambda实际上不是匿名的,它只使用一个隐式的__fn__
变量(应该重命名为其他变量,如双引导下划线名称是为编译器保留的,所以像yourapp__fn__
这样的东西会更好。)
所有这些本身都是在GCC复合声明中执行的(参见http://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html#Statement-Exprs),其基本格式如下:
({ ...; retval; })
复合语句的最后一个语句是刚刚声明的函数的地址。现在,int (*max)(int,int)
只被赋予复合语句的值,现在是指向刚声明的'anonymous'函数的指针。
调试宏当然是一种巨大的痛苦。
至于test;
..至少在这里的原因,我得到'测试重新声明为不同类型的符号',我认为这意味着GCC将其视为声明而不是(无用)表达。因为无类型变量默认为int
,并且因为您已将test
声明为函数(基本上是void (*)(void)
),所以你得到了......但我可能错了。
尽管如此,这在任何想象中都是不可移植的。
答案 2 :(得分:1)
部分答案: 它不是你感兴趣的int(* X)。它是int(* X)(y,z)。这是一个函数指针,指向名为X的函数,它接受(y,z)并返回int。
对于调试,这将非常困难。大多数调试器无法跟踪宏。您很可能必须调试程序集。
答案 3 :(得分:0)
int (*max)(int, int)
是您要声明的变量类型。它被定义为一个名为max的函数指针,它返回int,并将两个整数作为参数。
__fn__
是指函数名称,在本例中为max。
我在那里没有答案。如果你通过预处理器运行它,我想你可以逐步完成它。