C中函数内部的函数

Raf*_*ini 30 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;
}
Run Code Online (Sandbox Code Playgroud)

这在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)
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?

谢谢.

(编辑)抱歉这个可怜的例子.在我的原始代码中,我有点需要做这些事情.我正在使用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);

}
Run Code Online (Sandbox Code Playgroud)

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

double f(double x, void * par)
Run Code Online (Sandbox Code Playgroud)

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

jos*_*ick 30

嵌套函数在GCC中作为语言扩展提供,但它们不是标准语言的一部分,因此一些编译器不允许它们.


Jon*_*ler 22

其他人都给了你规范的答案"标准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!
}
Run Code Online (Sandbox Code Playgroud)

既然你说积分器等功能需要

  double (*f)(double x, void * par);
Run Code Online (Sandbox Code Playgroud)

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

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);
}
Run Code Online (Sandbox Code Playgroud)

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

double stuff(double a, double b)
{
    return integrate(f, &(struct parameters){a, b});
}
Run Code Online (Sandbox Code Playgroud)

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

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


Nos*_*dna 8

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

GCC中的运行时错误是拼写错误.inner_funcion应该是inner_function.


Dan*_*son 7

正如上面的许多答案所提到的,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; 
}
Run Code Online (Sandbox Code Playgroud)

请注意,这个答案不应该暗示我认为内部函数在您显示的用法中是个好主意.

几年后编辑:

C++现在允许我们使用lambdas作为内部函数.对于我上面的玩具示例,它看起来很像这样:

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

   double z;
   z = inner_function ();
   return z + y;
}
Run Code Online (Sandbox Code Playgroud)

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

更多信息:C++ 11中的lambda表达式是什么?