Вопрос:

Как вы передаете функцию в качестве параметра в C?

c function pointers syntax parameters

470906 просмотра

7 ответа

13326 Репутация автора

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

Автор: andrewrk Источник Размещён: 13.08.2008 02:16

Ответы (7)


3 плюса

4222 Репутация автора

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

Автор: saint_groceon Размещён: 13.08.2008 02:18

657 плюса

29135 Репутация автора

Решение

декларация

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

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

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

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

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

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

func(print);

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

Тело функции

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

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

Так funcкак объявление параметра говорит, что fэто имя для указателя на желаемую функцию, мы сначала напомним, что если fэто указатель, то *fэто то, на что fуказывает (то есть функция printв данном случае). В результате просто замените все вхождения 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

Автор: Niyaz Размещён: 13.08.2008 02:22

115 плюса

5330 Репутация автора

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

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::function<int (char a)> functiontype2;

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

Автор: roo Размещён: 13.08.2008 02:34

54 плюса

27568 Репутация автора

Начиная с 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);
}
Автор: Richard Размещён: 20.07.2015 04:24

13 плюса

1405 Репутация автора

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

#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();
}
Автор: Yogeesh H T Размещён: 23.11.2015 12:07

1 плюс

170 Репутация автора

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

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

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

void foo(int (*bar)(int, int));
Автор: doppelheathen Размещён: 27.11.2018 03:42

0 плюса

102 Репутация автора

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

#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;
}
Автор: Walter Размещён: 15.03.2019 02:46
32x32