代码之家  ›  专栏  ›  技术社区  ›  Rafael S. Calsaverini

C中函数内部的函数

  •  27
  • Rafael S. Calsaverini  · 技术社区  · 17 年前

    我正在编写一个与此类似的代码:

    #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中编译。

    国际商会提供:

    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 回复  |  直到 13 年前
        1
  •  20
  •   Jonathan Leffler    17 年前

    其他人都给了您规范化的答案“标准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});
    }
    

    “struct-parameters”类型只有几个变体的可能性非常大。您确实需要为各种函数提供单独的(足够)有意义的名称-您只能有一个函数调用' f '每个源文件。

    嵌套函数版本的唯一边际、微小的好处是,您可以确保除了 stuff 电话 f . 但是对于示例代码,这不是一个主要的好处;静态定义 f 表示除非向函数传递指针,否则此文件之外的任何函数都不能调用它。

        2
  •  30
  •   Adam Rosenfield    17 年前

    嵌套函数可用作 language extension in GCC 但它们不是标准语言的一部分,因此某些编译器不允许使用它们。

        3
  •  8
  •   Yamaneko    13 年前

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

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

        4
  •  6
  •   Community Mohan Dere    9 年前

    正如上面许多答案所提到的,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?

        5
  •  3
  •   anon    17 年前

    您使用的是嵌套函数-c不支持这样的功能。

        6
  •  1
  •   Naveen    17 年前

    这不是有效的C代码,C中不支持内部函数

        7
  •  1
  •   aJ.    17 年前

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

        8
  •  1
  •   Shawn Chin    17 年前

    嵌套函数不是C标准的一部分。因此,不能保证它对所有编译器都有效,并且应该绝对避免。

        9
  •  1
  •   Nick Presta    17 年前

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

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

    见 docs 更多信息。退房 -std 国旗也是。

        10
  •  0
  •   pjbeardsley    17 年前

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