В языке Си указатель на функцию может передаваться в другую функцию в качестве параметра. Например:
#include <stdio.h>
int sum(int x, int y)
{
return x+y;
}
int subtract(int x, int y)
{
return x-y;
}
int operation(int (*op)(int, int), int a, int b)
{
return op(a, b);
}
int main(void)
{
int a = 10;
int b = 5;
int result;
result = operation(sum, a, b);
printf("result = %d \n", result);
result = operation(subtract, a, b);
printf("result = %d \n", result);
return 0;
}
Здесь в функции operation первый параметр - указатель int (*op)(int, int) представляет функцию, которая возвращает значение типа int и
принимает два параметра типа int. Результатом функции является вызов той функции, на которую указывает указатель.
Определению указателя соответствуют две функции: sum и subtract, поэтому их адрес можно передать в вызов функции operation: operation(sum, a, b);.
Другой пример - функция, которая может принимать в качестве параметра некоторое условие:
#include <stdio.h>
int isEven(int x)
{
return x%2==0;
}
int isPositive(int x)
{
return x>0;
}
void action(int (*condition)(int), int numbers[], int n)
{
for(int i=0; i<n; i++)
{
if(condition(numbers[i])!=0)
{
printf("%d \t", numbers[i]);
}
}
}
int main(void)
{
int nums[] = {-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5};
int n = sizeof(nums)/sizeof(nums[0]);
printf("Even numbers: ");
action(isEven, nums, n);
printf("\nPositive numbers: ");
action(isPositive, nums, n);
return 0;
}
Первый параметр функции action - указатель int (*condition)(int) представляет функцию, которая принимает целое число и в зависимости от того, соответствует оно условию или нет, возвращает 1 (если соответствует) или 0.
На момент определения функции action точное условие может быть неизвестно.
В текущей программе условия представлены двумя функциями. Функция isEven() возвращает 1, если число четное, и 0, если число нечетное.
А функция isPositive() возвращает 1, если число положительное, и 0, если отрицательное.
При вызове функции action() в нее можно передать нужное условие: action(isEven, nums, n);. В итоге программа выведет на экран
числа из массива nums, которые соответствуют переданному условию:
Even numbers: -4 -2 0 2 4 Positive numbers: 1 2 3 4 5
Но применение указателей на функцию в качестве параметров ухудшает читабельность определения функции. В этом случае можно определить псевдоним для типа функции:
#include <stdio.h>
typedef int (binary_op)(int, int);
int sum(int x, int y) { return x + y;}
int subtract(int x, int y) { return x - y;}
int operation(binary_op op, int a, int b)
{
return op(a, b);
}
int main(void)
{
printf("result = %d \n", operation(sum, 10, 5)); // result = 15
printf("result = %d \n", operation(subtract, 10, 5)); // result = 5
return 0;
}
В данном случае для функций, которые имеют два параметра типа int и возращают значение типа int, определен псевдоним binary_op.
typedef int (binary_op)(int, int);
И далее мы можем использовать этот псевдоним как тип для определения параметров:
int operation(binary_op op, int a, int b)
{
return op(a, b);
}