Мини-памятка для начинающих С-водов.
Переменная-указатель на функцию. Как сделать и как пользоваться.
При помощи указателя можно получить доступ к содержимому переменной. Это просто.
Аналогичный способ существует и для обращения к функции. И он тоже не сложный.
Очевидно, что реализация этого способа требует определения указателя на функцию.
Делается это достаточно просто, путем объявления переменной соответствующего типа:
int (*funcptr)(int, int);
Этот пример объявляет переменную funcptr типа указатель на функцию, возвращающую результат типа int и имеющую 2 параметра типа int. Запись выглядит слегка шиворот-навыворот, но так уж требует Си - сначала нужно указать тип результата функции, затем обязательно в круглых скобках идентификатор функции (главное не забыть про звездочку – признак указателя), а затем, опять в круглых скобках, список типов параметров функции. Имена параметров тут не нужны и не важны.
Сделанная запись – не что иное, как объявление переменной с новым типом.
Можно определить этот тип при помощи typedef, после чего определять указатели на функции станет легче:
// тип указателя на функцию с 2 аргументами int и результатом int
typedef int (*t_func)(int, int);
// переменная - указатель на функцию
t_func funcptr;
Обращение к функции по указателю еще проще, чем обращение к переменной по указателю - в данном случае операция разыменования указателя не используется:
i = funcptr(3, 12);
Но следует помнить, что переменную-указатель нужно инициализировать. Иначе обращение к ней приведет к непредсказуемым последствиям.
Присвоение переменной адреса существующей функции очень простое.
Есть функция
int my_function(int x, int y){
return x + y;
}
Её можно присвоить переменной funcptr:
funcptr = my_function;
С этого момента обращение к funcptr будет по факту обращением к my_function.
Адрес функции можно передавать как параметр какой то процедуры точно так же, как и другие переменные.
Помним, что у нас выше объявлен тип t_func.
Пусть есть две функции:
int my_sum(int x, int y){
return x + y;
}
int my_mul(int x, int y){
return x * y;
}
Делаем процедуру-агрегатор:
int agr_func(int x, int y, t_func fun){
return fun(x,y);
}
Параметр fun с типом t_func (выделено желтым) - ни что иное, как обычный указатель на функцию. А вызов fun(x,y) - ни что иное, как вызов функции, адрес которой нам передан в параметре fun.
В основной программе делаем так:
i = agr_func(3, 4, my_sum);
j = agr_func(3, 4, my_mul);
в результате в i попадет сумма 3+4, а в j - произведение 3*4.
Очень доступно написано. Спасибо!
ОтветитьУдалитьПросто и доступно! Спасибо за статью.
ОтветитьУдалить