Как вы передаете функцию в качестве параметра в C? - PullRequest
538 голосов
/ 13 августа 2008

Я хочу создать функцию, которая выполняет функцию, передаваемую параметром для набора данных. Как передать функцию в качестве параметра в C?

Ответы [ 7 ]

669 голосов
/ 13 августа 2008

Декларация

Прототип для функции, которая принимает параметр функции, выглядит следующим образом:

void func ( void (*f)(int) );

Это означает, что параметр f будет указателем на функцию, которая имеет тип возврата void и которая принимает единственный параметр int. Следующая функция (print) является примером функции, которая может быть передана в func в качестве параметра, потому что это правильный тип:

void print ( int x ) {
  printf("%d\n", x);
}

вызов функции

При вызове функции с параметром функции передаваемое значение должно быть указателем на функцию. Используйте имя функции (без скобок) для этого:

func(print);

вызовет func, передав ему функцию печати. ​​

Функция Body

Как и любой параметр, func теперь может использовать имя параметра в теле функции для доступа к значению параметра. Допустим, что func будет применять функцию переданную к числам 0-4. Сначала рассмотрим, как будет выглядеть цикл для непосредственного вызова print:

for ( int ctr = 0 ; ctr < 5 ; ctr++ ) {
  print(ctr);
}

Поскольку объявление параметров func говорит, что f - это имя для указателя на нужную функцию, мы сначала напомним, что если f является указателем, то *f - это то, на что указывает f до (т.е. функция print в данном случае). В результате просто замените все вхождения печати в цикле выше на *f:

void func ( void (*f)(int) ) {
  for ( int ctr = 0 ; ctr < 5 ; ctr++ ) {
    (*f)(ctr);
  }
}

С http://math.hws.edu/bridgeman/courses/331/f05/handouts/c-c++-notes.html

119 голосов
/ 13 августа 2008

На этот вопрос уже есть ответ для определения указателей на функции, однако они могут стать очень запутанными, особенно если вы собираетесь передавать их по своему приложению. Чтобы избежать этой неприятности, я бы порекомендовал вам ввести указатель функции во что-то более читабельное. Например.

typedef void (*functiontype)();

Объявляет функцию, которая возвращает void и не принимает аргументов. Чтобы создать указатель на функцию этого типа, теперь вы можете сделать:

void dosomething() { }

functiontype func = &dosomething;
func();

Для функции, которая возвращает int и принимает символ, вы должны сделать

typedef int (*functiontype2)(char);

и использовать его

int dosomethingwithchar(char a) { return 1; }

functiontype2 func2 = &dosomethingwithchar
int result = func2('a');

Существуют библиотеки, которые могут помочь превратить указатели функций в удобные для чтения типы. Библиотека boost великолепна и стоит усилий!

boost::function<int (char a)> functiontype2;

намного приятнее, чем выше.

58 голосов
/ 20 июля 2015

Начиная с C ++ 11, вы можете использовать функциональную библиотеку , чтобы сделать это кратко и обобщенно. Синтаксис, например,

std::function<bool (int)>

где bool - это тип возвращаемого значения функции с одним аргументом, первый аргумент которой имеет тип int.

Я включил пример программы ниже:

// g++ test.cpp --std=c++11
#include <functional>

double Combiner(double a, double b, std::function<double (double,double)> func){
  return func(a,b);
}

double Add(double a, double b){
  return a+b;
}

double Mult(double a, double b){
  return a*b;
}

int main(){
  Combiner(12,13,Add);
  Combiner(12,13,Mult);
}

Однако иногда удобнее использовать функцию шаблона:

// g++ test.cpp --std=c++11

template<class T>
double Combiner(double a, double b, T func){
  return func(a,b);
}

double Add(double a, double b){
  return a+b;
}

double Mult(double a, double b){
  return a*b;
}

int main(){
  Combiner(12,13,Add);
  Combiner(12,13,Mult);
}
14 голосов
/ 23 ноября 2015

Передача адреса функции в качестве параметра другой функции , как показано ниже

#include <stdio.h>

void print();
void execute(void());

int main()
{
    execute(print); // sends address of print
    return 0;
}

void print()
{
    printf("Hello!");
}

void execute(void f()) // receive address of print
{
    f();
}

Также мы можем передать функцию в качестве параметра, используя указатель на функцию

#include <stdio.h>

void print();
void execute(void (*f)());

int main()
{
    execute(&print); // sends address of print
    return 0;
}

void print()
{
    printf("Hello!");
}

void execute(void (*f)()) // receive address of print
{
    f();
}
4 голосов
/ 13 августа 2008

Вам необходимо передать указатель на функцию . Синтаксис немного громоздкий, но он становится действительно мощным, когда вы с ним познакомитесь.

1 голос
/ 15 марта 2019

На самом деле это не функция, а локализованный фрагмент кода. Конечно, он не передает код только результат. Он не будет работать, если он будет передан диспетчеру событий для запуска в более позднее время (так как результат рассчитывается сейчас, а не когда происходит событие). Но он локализует ваш код в одном месте, если это все, что вы пытаетесь сделать.

#include <stdio.h>

int IncMultInt(int a, int b)
{
    a++;
    return a * b;
}

int main(int argc, char *argv[])

{
    int a = 5;
    int b = 7;

    printf("%d * %d = %d\n", a, b, IncMultInt(a, b));

    b = 9;

    // Create some local code with it's own local variable
    printf("%d * %d = %d\n", a, b,  ( { int _a = a+1; _a * b; } ) );

    return 0;
}
1 голос
/ 27 ноября 2018

Функции могут быть «переданы» как указатели на функции, согласно 6.7.6.3p8: « Объявление параметра как функции, возвращающего тип», должно быть настроено на «указатель на функцию, возвращающую тип» , как в 6.3.2.1.". Например, это:

void foo(int bar(int, int));

эквивалентно этому:

void foo(int (*bar)(int, int));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...