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

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

13.08.2008 02:16:32
Если вы используете функции / массивы в качестве переменных, ВСЕГДА используйте typedef.
Mooing Duck 13.01.2014 21:09:49
Мы называем это указателем на функцию
AminM 1.04.2014 11:11:48
Имя функции должно быть понятием для функции. Большинство людей, изучающих C, рано или поздно изучают qsort, что делает именно это?
mckenzm 3.07.2015 02:09:17
@ MooingDuck Я не согласен с вашим предложением, и в вашем предложении нет аргументов в поддержку этого вывода. Лично я предпочитаю никогда не использовать typedef для указателей на функции, и я думаю, что это делает код более понятным и легким для чтения.
andrewrk 16.12.2015 22:26:22
@andrewrk: Вы предпочитаете void funcA(void(*funcB)(int))и void (*funcA())()к typedef void funcB(); void funcA(funcB)и funcB funcA()? Я не вижу преимущества.
Mooing Duck 16.12.2015 23:27:23
7 ОТВЕТОВ
РЕШЕНИЕ

декларация

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

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

729
24.11.2015 01:59:51
В вашем первом и последнем примерах кода * не является обязательным. Как определение параметра функции, так и fвызов функции могут быть fтакими же, как и без *. Возможно, было бы неплохо сделать это так, как вы, чтобы было очевидно, что параметр f является указателем на функцию. Но это часто ухудшает читабельность.
Gauthier 22.02.2012 12:52:04
См. [C99, 6.9.1§14] для примеров. И то и другое верно, я просто хотел упомянуть альтернативу.
Gauthier 22.02.2012 12:58:02
В самом деле? Ответ с наивысшим рейтингом не содержит ни одной ссылки на использование typedefуказателей для функции? Извините, надо понизить голосование.
Jonathon Reinhart 1.10.2014 08:03:37
@JonathonReinhart, какие преимущества дает apprach 'typedef'? Хотя эта версия выглядит намного чище и лишена дополнительных утверждений. здесь довольно много.
Abhinav Gauniyal 22.02.2015 07:04:46
@JonathonReinhart хорошо заметили; Следует четко отметить, что указатели typedefs запутывают код и поэтому не должны использоваться.
M.M 24.11.2015 02:39:40

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

4
13.08.2008 02:18:28

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

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;

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

126
16.09.2008 13:22:06
Если вы хотите «превратить указатель функции в тип», вам не нужна библиотека boost. Просто используйте typedef; это проще и не требует дополнительных библиотек.
wizzwizz4 9.04.2016 11:50:42

Начиная с 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);
}
72
11.07.2017 14:02:36
Вопрос о С; C ++ здесь не применяется.
Super Cat 29.10.2015 23:44:06
Вопрос для C ++ ( stackoverflow.com/questions/6339970/… ) упоминается здесь, поэтому я думаю, что этот ответ на месте.
mr_T 24.03.2016 11:00:08
Может быть, вопрос о C ++ не стоит упоминать здесь, потому что этот вопрос для C.
Michael Fulton 19.04.2018 16:22:04
Этот вопрос возник в первую очередь, когда я искал «вызов функции c ++ как параметр», поэтому этот ответ, в любом случае, служит своей цели.
ufoxDan 7.11.2019 21:50:07

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

#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();
}
23
23.11.2015 13:20:07
Очень хороший ответ, с целыми блоками кода (вместо того, чтобы нарезать все в непонятный беспорядок). Не могли бы вы рассказать о различиях обеих техник?
Rafael Eyng 29.01.2020 15:17:27

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

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

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

void foo(int (*bar)(int, int));
5
5.02.2020 12:57:28
Из какого документа вы цитируете? Любая ссылка на это?
Rafael Eyng 29.01.2020 21:41:42
Я цитирую из стандарта ISO C11.
doppelheathen 5.02.2020 12:57:15

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

#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;
}
-2
15.03.2019 02:58:46
Вы просто вызываете функцию. Как бы вы передали какую-то другую функцию вместо IncMultInt?
Tejas Pendse 28.11.2019 05:27:14