在c中定义函数内部的函数

时间:2013-10-22 19:26:33

标签: c++ c

我想创建一个通用函数,它返回一个函数指针,指向C / C ++中的另一个函数。但是,第二个返回的函数应该能够使用第一个函数的变量。

实施例,

typedef double (*func_t)(double);

func_t inverse(func_t fn) {
   // define another function here that uses fn
   double solve(double x) {
      // use fn
   }
   return &solve;
}

double sqr(double x) { return x * x; }

int main() {
     func_t inv = inverse(sqr);
     printf("sqrt %d = %f\n", 100, inv(100)); 
}

显然gcc,g ++不允许我这样做。我可以在不使用类或结构的情况下实现此目的。

8 个答案:

答案 0 :(得分:5)

回答C:

C不支持嵌套函数(在另一个函数中定义函数),但gcc允许它作为C的GNU扩展。

http://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html

答案 1 :(得分:5)

这是关于嵌套函数的 ;这是关闭。 GCC的嵌套函数是一种半实现的闭包形式,不会执行问题所要求的。

按照任何标准,C都不支持闭包。

C ++ 11支持通过lambdas进行闭包,还有一些其他特定于C ++的解决方案。

Apple的Clang编译器 支持闭包作为C模式的扩展,以“块”的形式。与嵌套函数不同,这些函数实际上适用于请求的用例(即返回到更高的调用级别)。

你会写出这样的东西:

typedef double (^func_t)(double);  // block type is slightly different from function pointer

func_t inverse(func_t fn) {
   return ^ double(double x) {
       //use fn
   };
}

// ...etc., same from here

但是如果你想大量使用闭包,你真的需要使用不同的语言。由于缺乏任何类型的内存管理,你会在C中遇到严重的并发症(无限制的闭包是手工管理的噩梦)。

答案 2 :(得分:4)

这在带有lambda:

的C ++ 11中是可行的
#include <cstdio>
#include <cmath>
#include <functional>

typedef std::function<double(double)> func_t;

func_t inverse(func_t fn) {
    return [=](double x) { printf("fn(x): %f\n", fn(x)); return sqrt(x); };
}

double sqr(double x) { return x * x; }

int main() {
    auto inv = inverse(sqr);
    printf("sqrt %d = %f\n", 100, inv(100));
}

答案 3 :(得分:2)

如果你可以使用C ++ 11,那么lambda函数就是你的朋友:

#include <functional>
#include <iostream>

std::function<double(double)> identity(std::function<double(double)> fn)
{
  return [fn](double x){
    // Do your logic here
    return fn(x);
  };
}

double sqr(double x) { return x * x; }

int main() {
  auto f = identity(sqr);
  std::cout << "sqr(100) = " << f(100) << std::endl;
}

如果您不打算支持C ++ 11,可以这样做:

#include <iostream>

typedef double (*func_t)(double);
struct func
{
  func_t fn;
  double (*calc)(func_t, double);
  double operator()(double x) {return calc(fn, x);}
};

double identity_calc(func_t fn, double x) {return fn(x);}

func identity(func_t fn)
{
  func f = {fn, identity_calc};
  return f;
}

double sqr(double x) { return x * x; }

int main() {
  func f = identity(sqr);
  std::cout << "sqr(100) = " << f(100) << std::endl;
}

但我不认为你会用普通的C运气好。

答案 4 :(得分:1)

  

在c?

中定义函数内部的函数

称为嵌套函数。

嵌套函数不是 ANSI C 的一部分,但是they are part of Gnu C

来自维基百科

支持词法嵌套函数的众所周知的语言包括:

  

基于ALGOL的语言,如ALGOL 68,Simula,Pascal,Modula-2,Modula-3,Oberon,Seed7和Ada。

     

Lisp的现代版本(带有词法范围),例如Scheme和Common Lisp。

     

ECMAScript(JavaScript和ActionScript)。

     

Scala(全力支持)

     

Ruby,Python,Perl等脚本语言的不同程度的支持(从版本6开始)。

     

标准C和C ++不支持嵌套函数,但是:GCC支持C语言中的嵌套函数,作为语言扩展。

     

与C相关的D语言具有嵌套函数。

     

Fortran,从Fortran-90开始,支持一级嵌套(CONTAINed)子程序和函数。

     

MATLAB(全力支持)

GNU C语法示例(使用嵌套函数进行C扩展):

float E(float x)
{
    float F(float y)
    {
        return x + y;
    }
    return F(3) + F(4);
}

答案 5 :(得分:1)

标准C中不允许使用嵌套函数

但是可以使用as a language extension in GCC

因为问题是用C ++标记的。 C ++也不支持嵌套函数。您可能有这样的解决方法: -

int main() 
{
  struct ABC {
    static void xyz()
    {
    }
  };

  ABC::xyz();

  return 0;
}

即,您可以拥有本地课程。

答案 6 :(得分:1)

comp.lang.c FAQ list · Question 20.24

  

实现嵌套函数并不容易,因为它们可以正确访问包含函数中的局部变量,因此它们被故意排除在C之外作为简化。 (gcc允许它们作为扩展。)对于嵌套函数的许多潜在用途(例如qsort比较函数),一个适当的,如果稍微麻烦的解决方案是使用具有静态声明的相邻函数,必要时通过一些静态变量进行通信。 (虽然qsort不支持,但更简洁的解决方案是传递指向包含必要上下文的结构的指针。)

答案 7 :(得分:-1)

通常您在额外的文件/模块中编写函数。 使你的内在功能保持静止,外面没有人可以使用它。

MFG