Определяя функцию внутри функции из 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++ не позволяют мне это делать. Могу ли я достичь этого без использования классов или структур.

Ответ 1

Ответ на C:

C не поддерживает вложенные функции (определяющие функцию внутри другой функции), но gcc позволяет использовать ее как расширение GNU для C.

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

Ответ 2

Это не о вложенных функциях; речь идет о закрытии. Вложенные функции GCC представляют собой полуприведенную форму закрытия, которая не делает то, что задает вопрос.

C, идущий по любому из стандартов, не поддерживает закрытие вообще.

С++ 11 поддерживает замыкания через lambdas, а также есть несколько других решений, специфичных для С++.

Компилятор 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 из-за отсутствия какого-либо управления памятью (неограниченное закрытие - это кошмар для управления вручную).

Ответ 3

Это возможно в С++ 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));
}

Ответ 4

Если вы можете использовать С++ 11, их лямбда-функции являются вашим другом:

#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;
}

Если вы не планируете поддерживать С++ 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.

Ответ 5

определяющий функцию внутри функции из c?

Называется функция Nested.

Вложенные функции не являются частью ANSI C, однако они являются частью 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 и С++ не поддерживают вложенные функции, но: GCC поддерживает вложенные функции в C как расширение языка.

Язык D, который связан с C, имеет вложенные функции.

Fortran, начиная с Fortran-90, поддерживает один уровень вложенных (CONTAINed) подпрограмм и функций.

MATLAB (полная поддержка)

Пример в синтаксисе GNU C (C-расширенный с вложенными функциями):

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

Ответ 6

Вложенные функции не допускаются в стандартном C

Однако они доступны как расширение языка в GCC

Так как вопрос помечен в С++. С++ также не поддерживает вложенные функции. Возможно, у вас есть обходной путь: -

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

  ABC::xyz();

  return 0;
}

т.е. вы можете иметь локальные классы.

Ответ 7

comp.lang.c Часто задаваемые вопросы · Вопрос 20.24:

Это не тривиально реализовать вложенные функции, так что они имеют надлежащий доступ к локальным переменным в содержащей (ых) функциях (-ах), поэтому они были намеренно исключены из C в качестве упрощения. (gcc разрешает их как расширение). Для многих потенциальных применений вложенных функций (например, функций сравнения qsort) адекватное, если немного громоздкое решение - использовать смежную функцию со статическим объявлением, сообщая при необходимости через несколько статических переменных. (Чистое решение, хотя и не поддерживается qsort, должно передавать указатель на структуру, содержащую необходимый контекст.)

Ответ 8

Обычно вы записываете свои функции в дополнительный файл/модуль. Сделайте свою внутреннюю функцию статической, и никто из нее не сможет ее использовать.

MFG