Я хочу создать функцию, которая выполняет функцию, переданную параметром для набора данных. Как передать функцию в качестве параметра в C?
Как передать функцию в качестве параметра в C?
Ответы (8)
Декларация
Прототип функции, которая принимает параметр функции, выглядит следующим образом:
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);
}
}
f
могут принимать f
, как и без *. Было бы неплохо сделать это так же, как и вы, чтобы было очевидно, что параметр f является указателем на функцию. Но читабельность часто ухудшается.
- person Gauthier; 22.02.2012
typedef
для указателей на функции? Извините, я должен проголосовать против.
- person Jonathon Reinhart; 01.10.2014
*
при объявлении указателя на функцию, правильно? Потому что вы не можете определить функцию из определения типа функции. Существует много информации об указателях функций, определяющих типы, но не о типах функций.
- person Jonathon Reinhart; 24.11.2015
На этот вопрос уже есть ответ для определения указателей функций, однако они могут быть очень запутанными, особенно если вы собираетесь передавать их по своему приложению. Чтобы избежать этой неприятности, я бы порекомендовал вам ввести указатель функции в более читаемый формат. Например.
typedef void (*functiontype)();
Объявляет функцию, которая возвращает void и не принимает аргументов. Чтобы создать указатель на функцию этого типа, вы можете:
void dosomething() { }
functiontype func = &dosomething;
func();
Для функции, которая возвращает int и принимает char, вы бы сделали
typedef int (*functiontype2)(char);
и использовать это
int dosomethingwithchar(char a) { return 1; }
functiontype2 func2 = &dosomethingwithchar
int result = func2('a');
Существуют библиотеки, которые могут помочь превратить указатели функций в удобные для чтения типы. Библиотека boost function великолепна и стоит того усилие!
boost::function<int (char a)> functiontype2;
намного лучше, чем выше.
typedef
; это проще и не требует дополнительных библиотек.
- person wizzwizz4; 09.04.2016
Начиная с 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: "Объявление параметра как '' функция, возвращающая тип '' должно быть изменено на '' указатель на функцию, возвращающую тип '' < / em>, как в 6.3.2.1. ". Например, это:
void foo(int bar(int, int));
эквивалентно этому:
void foo(int (*bar)(int, int));
Вам необходимо передать указатель на функцию. Синтаксис немного громоздкий, но он действительно эффективен, как только вы с ним познакомитесь.
Я собираюсь объяснить это на простом примере кода, который принимает функцию compare
в качестве параметра другой функции sorting
. Допустим, у меня есть функция пузырьковой сортировки, которая принимает настраиваемую функцию сравнения и использует ее вместо фиксированного оператора if.
Функция сравнения
bool compare(int a, int b) {
return a > b;
}
Теперь пузырьковая сортировка, которая принимает другую функцию в качестве параметра для выполнения сравнения
Функция пузырьковой сортировки
void bubble_sort(int arr[], int n, bool (&cmp)(int a, int b)) {
for (int i = 0;i < n - 1;i++) {
for (int j = 0;j < (n - 1 - i);j++) {
if (cmp(arr[j], arr[j + 1])) {
swap(arr[j], arr[j + 1]);
}
}
}
}
Наконец, main
, который вызывает функцию пузырьковой сортировки, передавая логическую функцию сравнения в качестве аргумента.
int main()
{
int i, n = 10, key = 11;
int arr[10] = { 20, 22, 18, 8, 12, 3, 6, 12, 11, 15 };
bubble_sort(arr, n, compare);
cout<<"Sorted Order"<<endl;
for (int i = 0;i < n;i++) {
cout << arr[i] << " ";
}
}
Выход:
Sorted Order
3 6 8 11 12 12 15 18 20 22
На самом деле это не функция, но это локализованный фрагмент кода. Конечно, он не передает код только результат. Он не будет работать, если будет передан диспетчеру событий для запуска позже (поскольку результат рассчитывается сейчас, а не при возникновении события). Но он локализует ваш код в одном месте, если это все, что вы пытаетесь сделать.
#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
?
- person Tejas Pendse; 28.11.2019
typedef
. - person Mooing Duck   schedule 14.01.2014void funcA(void(*funcB)(int))
иvoid (*funcA())()
typedef void funcB(); void funcA(funcB)
иfuncB funcA()
? Я не вижу положительных моментов. - person Mooing Duck   schedule 17.12.2015qsort
иbsearch
. - person Bob Jarvis - Reinstate Monica   schedule 15.02.2021