2014-12-04 2 views
0

В file1.hПередача функции в другую как указатель с разными аргументами длины?

// find the root of a function of one variable 
double rootfind(double (*fp)(double), double start, double end); 

В file2.h

// a function of multiple variables 
double myfun(double a, double b); 

double test(); 

В file2.c

double myfun(double a, double b) 
{ 
    return (a+3.0)*(a-1.0)*(a-1.0)*b; 
} 

double test() 
{ 
    double b, start, end; 

    start = -4.0; 
    end = 4.0/3.0; 

    b = 2.0; 

    // How do I use the rootfinding function to find the root of myfun 
    // where b is set as a constant in this function? 
    // How do i find the root of myfun(x,2.0)? 
} 

Я хочу, чтобы сохранить функцию rootfind родовое и не передать дополнительные параметры. Я также не хочу использовать расширение gcc для вложенных функций.

ответ

2

Вы спрашиваете о чем-то известном как замыкания, которые не поддерживаются в стандартном C90/C99. Если вы планируете это делать, вам либо необходимо:

  • Используйте расширение GCC, которое вы упомянули.
  • Используйте функцию std::bind C++.
  • Используйте библиотеку (такую ​​как libffi, которая поставляется вместе с GCC), чтобы выделить память, в которую можно записать и запустить (вы создаете машинный код для новой функции одного аргумента во время выполнения).
  • Напишите статическую функцию верхнего уровня, которая работает так, как вы хотите.
  • Используйте динамически загруженный модуль, который вы компилируете из кода C во время выполнения.

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


примером статической функции верхнего уровня (место это чуть выше main функции):

static myfun_single_b = 2.0; 

static double myfun_single(double a) { 
    return myfun(a, myfun_single_b); 
} 

причина мы используем static keywor d здесь, так что имя переменной и имя функции не будут конфликтовать с другими именами функций/переменных из других исходных файлов.

+0

Спасибо. Теперь я знаю, как его зовут, поэтому я могу его найти. Не могли бы вы объяснить, что вы подразумеваете для способа статической функции верхнего уровня? – user1801359

1

Вы можете написать функцию обертку:

static double wrapper(double a) { 
    return myfun(a, 3.0); 
} 

и использовать rootfind() по этому вопросу. Вы могли бы сделать его более общий характер (т.е. поддерживать различные значения второго аргумента myfun()), сделав его принять значение второго аргумента myfun() «s из переменной файла Область применения:

static double b; 

static double wrapper(double a) { 
    return myfun(a, b); 
} 

Можно даже обобщить больше, делая обертку вызова функции два-ARG с помощью указателя функции файла области видимости:

static double b; 
static double (*wrapped)(double, double); 

static double wrapper(double a) { 
    return (*wrapped)(a, b); 
} 

это о пределе косвенности вы можете выполнить, но это дает достаточное количество широты.

1

Если вы можете изменить rootfind, правильный путь, чтобы исправить это было бы добавить параметр контекста указателя функции, как

double rootfind(double (*fp)(double, void *), double start, double end, void *context); 

Вы можете создать контекст-структуру, содержащую свой второй аргумент b и передать указатель на него через контекстный аргумент.

Таким образом, предотвращаются как глобальное состояние, так и время выполнения кода. Функция rootfind также остается общей.

Смежные вопросы