如何在C中将简单的匿名函数作为参数传递

时间:2011-08-10 16:02:32

标签: c

我确信之前已经问过这个问题的一些变体,但所有其他类似的关于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++;
}

6 个答案:

答案 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)

不,你不能。匿名函数仅在函数式语言(以及具有功能子集的语言)中可用,并且众所周知,c功能失调; ^)

答案 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 documentationClang's block language specificationimplementation 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++;
    }
}