В языке Си указатель на функцию может передаваться в другую функцию в качестве параметра. Например:
#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); }