Как создайтся функция обратного вызова? - C (СИ)
Формулировка задачи:
Покажите мастер-класс как создавать функции обратного вызова и использовать их.
Решение задачи: «Как создайтся функция обратного вызова?»
textual
Листинг программы
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
typedef int (*callback_t)(int, va_list);
void map_int_array(int *array, size_t n, callback_t f, ...)
{
va_list extra;
size_t i;
va_start(extra, f);
for(i = 0; i < n; ++i)
array[i] = f(array[i], extra);
va_end(extra);
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
int identity(int arg, va_list extra)
{
return arg;
}
int add(int arg, va_list extra)
{
int addend = va_arg(extra, int);
return arg + addend;
}
int add_two_numbers(int arg, va_list extra)
{
int add1 = va_arg(extra, int);
int add2 = va_arg(extra, int);
return arg + add1 + add2;
}
int constantly(int arg, va_list extra)
{
int value = va_arg(extra, int);
return value;
}
int print_array(int arg, va_list extra)
{
printf("%d\n", arg);
return arg;
}
int find_max(int arg, va_list extra)
{
int *max = va_arg(extra, int *);
if(arg > *max)
*max = arg;
return arg;
}
#pragma GCC diagnostic pop
int main(void)
{
int numbers[] = {5, 8, -2, 3, 6}, max;
const size_t n = sizeof numbers / sizeof *numbers;
puts("\nNumbers are");
map_int_array(numbers, n, print_array);
max = numbers[0];
map_int_array(numbers + 1, n - 1, find_max, &max);
printf("\nFind the max number: %d\n", max);
puts("\n...then run the identity function:");
map_int_array(numbers, n, identity);
map_int_array(numbers, n, print_array);
puts("\n...then add 3 to each number:");
map_int_array(numbers, n, add, 3);
map_int_array(numbers, n, print_array);
puts("\n...then subtract 4 and add 2:");
map_int_array(numbers, n, add_two_numbers, -4, 2);
map_int_array(numbers, n, print_array);
puts("\n...then replace each number with 42:");
map_int_array(numbers, n, constantly, 42);
map_int_array(numbers, n, print_array);
exit(EXIT_SUCCESS);
}
Объяснение кода листинга программы
- В функции
map_int_arrayиспользуется типcallback_t, который представляет собой указатель на функцию, принимающую два аргумента типаintи произвольное количество аргументов, переданных черезva_list. - Функция
map_int_arrayприменяет функцию обратного вызова к каждому элементу массива. - Функция
identityявляется функцией обратного вызова, которая просто возвращает переданный ей аргумент. - Функция
addявляется функцией обратного вызова, которая принимает два аргумента и возвращает их сумму. - Функция
add_two_numbersявляется функцией обратного вызова, которая принимает три аргумента и возвращает их сумму. - Функция
constantlyявляется функцией обратного вызова, которая принимает два аргумента и возвращает переданное значение. - Функция
print_arrayявляется функцией обратного вызова, которая принимает два аргумента и выводит переданное значение. - Функция
find_maxявляется функцией обратного вызова, которая находит максимальное значение в массиве. - В функции
mainопределен массивnumbersи его размерn. - Затем функция
map_int_arrayприменяется к массивуnumbersс функцией обратного вызоваprint_array, чтобы вывести значения массива. - Затем функция
find_maxприменяется к массивуnumbersс функцией обратного вызоваprint_arrayи переменнойmax, чтобы найти максимальное значение. - Затем функция
identityприменяется к массивуnumbersс функцией обратного вызоваprint_array, чтобы применить функцию обратного вызоваidentityк каждому элементу массива. - Затем функция
addприменяется к массивуnumbersс функцией обратного вызоваprint_arrayи числом 3, чтобы добавить 3 к каждому элементу массива. - Затем функция
add_two_numbersприменяется к массивуnumbersс функцией обратного вызоваprint_arrayи числами -4 и 2, чтобы вычесть 4 и добавить 2 к каждому элементу массива. - Затем функция
constantlyприменяется к массивуnumbersс функцией обратного вызоваprint_arrayи числом 42, чтобы заменить каждый элемент массива на 42. - В конце программы вызывается функция
exitс аргументомEXIT_SUCCESS, чтобы указать, что программа успешно завершилась. - Значение
EXIT_SUCCESSявляется константой, представляющей успешный результат выполнения программы. - Значение
nпредставляет собой размер массиваnumbers. - Значение
sizeofиспользуется для вычисления размера массиваnumbers. - Значение
numbersявляется массивом целых чисел, используемым в программе.