C中函数内部的函数

时间:2009-06-05 19:10:26

标签: c function

我正在制作与此类似的代码:

#include <stdio.h>

double some_function( double x, double y)
{
  double inner_function(double x)
  { 
    // some code
    return x*x;
  }

  double z;
  z = inner_function(x);
  return z+y;

}

int main(void)
{
  printf("%f\n", some_function(2.0, 4.0));
  return 0;
}

这在GCC中完美编译(没有警告)但无法在ICC中编译。

ICC给出:

main.c(16): error: expected a ";"
    { 
    ^

main.c(21): warning #12: parsing restarts here after previous syntax error
    double z;
            ^

main.c(22): error: identifier "z" is undefined
    z = inner_function(x);
    ^

compilation aborted for main.c (code 2)

我做错了什么?

感谢。

(编辑)抱歉这个糟糕的例子。在我的原始代码中,我有点需要做这些事情。我正在使用GSL数值积分器,有类似的东西:

double stuff(double a, double b)
{
  struct parameters
  {
    double a, b;
  };

  double f(double x, void * params)
  {
    struct parameters p = (struct parameters *) params;
    double a = p->a, b = b->b;
    return some_expression_involving(a,b,x);
  }
  struct parameters par = {a,b};

  integrate(&f, &par);

}

我有很多这种结构的函数:它们是函数与大量外部参数集成的结果。并且实现数值积分的函数必须接收指向类型函数的指针:

double f(double x, void * par)

我真的希望函数以这种方式嵌套,所以我的代码不会膨胀很多很多函数。我希望我能用ICC编译它以加快速度。

10 个答案:

答案 0 :(得分:30)

嵌套函数以language extension in GCC形式提供,但它们不是标准语言的一部分,因此有些编译器不允许这样做。

答案 1 :(得分:20)

其他人都给了你规范的答案“标准C中不允许使用嵌套函数”(所以使用它们取决于你的编译器)。

您修改后的示例是:

double stuff(double a, double b)
{
  struct parameters
  {
    double a, b;
  };

  double f(double x, void * params)
  {
    struct parameters p = (struct parameters *) params;
    double a = p->a, b = b->b;
    return some_expression_involving(a,b,x);
  }
  struct parameters par = {a,b};

  return integrate(&f, &par);     // return added!
}

因为您说积分器等功能需要

  double (*f)(double x, void * par);

我不明白为什么你真的需要嵌套函数。我希望写一下:

struct parameters
{
    double a, b;
};

static double f(double x, void *params)
{
    struct parameters p = (struct parameters *) params;
    double a = p->a, b = b->b;
    return some_expression_involving(a,b,x);
}

double stuff(double a, double b)
{
    struct parameters par = { a, b };
    return integrate(f, &par);
}

上面的代码应该在C89中起作用(除非像初始化'par'那样存在问题)或C99;此版本的代码仅适用于C99,使用参数的复合文字(第6.5.2.5节复合文字):

double stuff(double a, double b)
{
    return integrate(f, &(struct parameters){a, b});
}

“结构参数”类型只有少数变体的可能性非常大。您需要为各种函数提供单独的(充分)有意义的名称 - 每个源文件只能有一个名为“f”的函数。

嵌套函数版本唯一的微不足道的好处是,您可以确保除了stuff之外没有其他函数调用f。但是考虑到示例代码,这不是主要的好处; f的静态定义意味着除非传递指向函数的指针,否则此文件外的任何函数都不能调用它。

答案 2 :(得分:8)

C没有嵌套函数。 GCC的嵌套函数是该语言的扩展。

GCC中的运行时错误是拼写错误。 inner_funcion应为inner_function

答案 3 :(得分:6)

正如上面的许多答案所提到的,C中不支持内部函数,但是内部可以在C ++中用来完成类似的事情。不幸的是,它们使用起来有点笨拙,但如果您不介意编译为C ++,它可能是您的选择。

未经测试的例子:

double some_function( double x, double y)
{
  struct InnerFuncs
  {
    double inner_function(double x)
    { 
      // some code
      return x*x;
    }
    // put more functions here if you wish...
  } inner;

  double z;
  z = inner.inner_function(x);
  return z+y; 
}

请注意,这个答案不应该暗示我认为内部函数在你所使用的用法中是一个好主意。

年后编辑:

C ++现在允许我们使用lambdas作为内部函数。就我上面的玩具示例而言,它看起来很像:

double some_function( double x, double y)
{
   auto inner_function = [&]() { return x * x; }

   double z;
   z = inner_function ();
   return z + y;
}

请注意,局部变量x会自动在lambda中捕获,这是一个非常好的功能。

更多信息:What is a lambda expression in C++11?

答案 4 :(得分:3)

您正在使用嵌套函数 - C不支持此类内容。

答案 5 :(得分:1)

这不是有效的C代码,C

不支持内部函数

答案 6 :(得分:1)

函数内的局部函数定义在C中是非法的。

答案 7 :(得分:1)

嵌套函数不是C标准的一部分。因此,无法保证它适用于所有编译器,绝对应该避免使用。

答案 8 :(得分:1)

如果您想知道如何关闭GCC扩展等等。

您可以使用基本上将标准设置为c89的-ansi标志,并关闭与ISO C90不兼容的GCC功能。

有关详细信息,请参阅docs。查看-std标志。

答案 9 :(得分:0)

我不是专家,但我愿意打赌这是C99规范明确禁止或未定义的,所以最好远离它。