Я хочу создать функцию, которая выполняет функцию, передаваемую параметром для набора данных. Как вы передаете функцию в качестве параметра в C?
декларация
Прототип функции, которая принимает параметр функции, выглядит следующим образом:
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
f
вызов функции могут быть f
такими же, как и без *. Возможно, было бы неплохо сделать это так, как вы, чтобы было очевидно, что параметр f является указателем на функцию. Но это часто ухудшает читабельность. typedef
указателей для функции? Извините, надо понизить голосование. На этот вопрос уже есть ответ для определения указателей на функции, однако они могут быть очень запутанными, особенно если вы собираетесь передавать их по своему приложению. Чтобы избежать этой неприятности, я бы порекомендовал вам ввести указатель функции во что-нибудь более читаемое. Например.
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;
это намного приятнее, чем выше.
typedef
; это проще и не требует дополнительных библиотек. Начиная с 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);
}
Передать адрес функции в качестве параметра другой функции, как показано ниже
#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();
}
Функции могут быть «переданы» как указатели на функции, в соответствии с ISO C11 6.7.6.3p8: « Объявление параметра как« функции, возвращающего тип »должно быть настроено на« указатель на функцию, возвращающую тип » , как в 6.3 .2.1. " Например, это:
void foo(int bar(int, int));
эквивалентно этому:
void foo(int (*bar)(int, int));
На самом деле это не функция, а локализованный фрагмент кода. Конечно, он не передает код только результат. Он не будет работать, если он будет передан диспетчеру событий для запуска в более позднее время (так как результат рассчитывается сейчас, а не когда происходит событие). Но он локализует ваш код в одном месте, если это все, что вы пытаетесь сделать.
#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;
}
IncMultInt
?
typedef
.void funcA(void(*funcB)(int))
иvoid (*funcA())()
кtypedef void funcB(); void funcA(funcB)
иfuncB funcA()
? Я не вижу преимущества.