我确信之前已经问过这个问题的一些变体,但所有其他类似的关于SO的问题似乎要复杂得多,包括传递数组和其他形式的数据。我的场景简单得多,所以我希望有一个简单/优雅的解决方案。
有没有办法可以创建匿名函数,或者将一行代码作为函数指针传递给另一个函数?
就我而言,我有一系列不同的操作。在每行代码之前和之后,我想要完成的任务永远不会改变。我不想复制开头代码和结束代码,而是编写一个函数,它将函数指针作为参数并以必要的顺序执行所有代码。
我的问题是,为每个操作定义30个函数是不值得的,因为它们都是一行代码。如果我无法创建匿名函数,有没有办法可以简化我的C代码?
如果我的要求不完全清楚。这里有一些伪代码用于澄清。我的代码比这更有意义,但下面的代码得到了相应的点。
void Tests()
{
//Step #1
printf("This is the beginning, always constant.");
something_unique = a_var * 42; //This is the line I'd like to pass as an anon-function.
printf("End code, never changes");
a_var++;
//Step #2
printf("This is the beginning, always constant.");
a_diff_var = "arbitrary"; //This is the line I'd like to pass as an anon-function.
printf("End code, never changes");
a_var++;
...
...
//Step #30
printf("This is the beginning, always constant.");
var_30 = "Yup, still executing the same code around a different operation. Would be nice to refactor..."; //This is the line I'd like to pass as an anon-function.
printf("End code, never changes");
a_var++;
}
答案 0 :(得分:9)
不是传统意义上的匿名函数,但你可以将其宏观化:
#define do_something(blah) {\
printf("This is the beginning, always constant.");\
blah;\
printf("End code, never changes");\
a_var++;\
}
然后它变成
do_something(something_unique = a_var * 42)
答案 1 :(得分:4)
答案 2 :(得分:2)
在C和pre-0x C ++中,没有。
在C ++ 0x中,是的,使用lambda functions。
答案 3 :(得分:2)
简化代码的最佳方法可能是在switch语句周围放置一个for循环。
int a_var;
for ( a_var = 0; a_var <= 30; a_var++ )
{
starteroperations();
switch (a_var)
{
case 0:
operation0(); break;
case ...:
operationx(); break;
case 30:
...
}
closingoperations();
}
答案 4 :(得分:0)
如果你可以使用Clang,你可以利用块。要学习块,您可以使用Apple's documentation,Clang's block language specification和implementation notes以及Apple's proposal to the ISO C working group向标准C语言添加块,以及大量博客帖子。< / p>
使用块,你可以写:
/* Block variables are declared like function pointers
* but use ^ ("block pointer") instead of * ("normal pointer"). */
void (^before)(void) = void ^(void) { puts("before"); };
/* Blocks infer the return type, so you don't need to declare it
* in the block definition. */
void (^after)(void) = ^(void) { puts("after"); };
/* The default arguments are assumed to be void, so you could even
* just define after as
*
* ^{ puts("after"); };
*/
before();
foo = bar + baz*kablooie;
after();
此示例通过分配块变量来提供匿名块名称。您也可以直接定义和调用块:
^{ puts("!"); } ();
/*| definition | invocation of anonymous function |*/
这也使得定义“struct-objects”(使用结构的C中的OOP)变得非常简单。
Clang和GCC都支持inner/nested functions作为标准C的扩展。这将允许您在获取其地址之前立即定义该函数,如果您的控制流结构允许它可能是另一种选择:内部函数指针不能被允许逃离他们的直接范围。正如文档所说:
如果你尝试在包含函数退出后通过其地址调用嵌套函数,那么一切都将破坏。如果你试图在包含范围级别退出后调用它,并且如果它引用了一些不再在范围内的变量,那么你可能很幸运,但冒风险并不明智。但是,如果嵌套函数没有引用超出范围的任何内容,那么您应该是安全的。
使用嵌套函数,您可以编写:
/* Nested functions are defined just like normal functions.
* The difference is that they are not defined at "file scope"
* but instead are defined inside another function. */
void before(void) { puts("before"); };
void after(void) { puts("after"); };
before();
foo = bar + baz*kablooie;
after();
答案 5 :(得分:0)
您可以使用@dcpomero建议的case
方式,也可以执行以下操作:
typedef void job(int);
job test1; void test1(int a_var) { something_unique = a_var * 42; }
job test2; void test2(int a_var) { a_diff_var = "arbitrary"; }
job test3; void test3(int a_var) { var_30 = "Yup, still executing the same code around a different operation. Would be nice to refactor..."; }
job * tests[] = { test1, test2, test3, testn };
void Tests()
{
int i;
for (i=0; i < sizeof tests/sizeof tests[0]; i++) {
printf("This is the beginning, always constant.");
tests[i](a_var);
printf("End code, never changes");
a_var++;
}
}