функция от функции (вложенной) - си
Искала, как задать функцию от функции.
Вопросы:
- правилен ли вариант 1,
- можно ли пользоваться вариантом 2,
- и если оба неправильные (то есть могут привести к ошибкам), то как надо писать?
Чтобы работало и в C, и в C++, и не только с gcc.
В кн. Кернигана, Ричи "Язык программирования си" 2009 на стр 131 есть пример, но там не очень ясно:
comp
— указатель на функцию, (*comp
) — сама функция.
Определения функции (*comp
) в книге не нашла.
Попыталась написать простой пример, максимально приближенный к книге: вариант 1.
Первая функция - сумма, вторая - квадрат первой.
Но работает (eclipse
, gcc
, просто C
) и так, как во втором варианте: в конце main
в printf
внутренняя функция вызывается просто как f3
, без звездочек.
вариант 1:
int main(int argc, char *argv[]) {
int a = 2, b = 4;
int f1(int, int);
int f2(int x1, int x2, int (* pointer_to_f1)(int, int));
int (*p_f1) (int, int);
p_f1 = f1;
printf("f2 = %i \n", f2(a, b, p_f1) );
return 0;
};
int f1 (int x1, int x2) {
return (x1 + x2);
};
int f2(int x1, int x2, int (* pointer_to_f1)(int x1, int x2)) {
return ((* pointer_to_f1)(x1, x2) * (* pointer_to_f1)(x1, x2));
};
вариант 2:
int main(int argc, char *argv[]) {
int c = 4, d = 4;
int f3(int, int);
int f4(int x1, int x2, int f3(int, int));
printf("f4 = %i \n", f4(c, d, f3) );
return 0;
};
int f3 (int x1, int x2) {
return (x1 + x2);
};
int f4(int x1, int x2, int f3 (int x1, int x2)) {
return (f3(x1, x2) * f3(x1, x2));
};
Ответы (2 шт):
Сделала как могла примерно так, как на странице по Вашей ссылке (https://en.cppreference.com/w/c/algorithm/qsort), так правильно?
int f5 (int x1, int x2) {
return (x1 + x2);
};
int f6(int x1, int x2, int (* pointer_to_f5) (int x1, int x2)) {
return (* pointer_to_f5)(x1, x2) * (* pointer_to_f5)(x1, x2);
}; // обязательно ли тут писать "(* pointer_to_f5)" (можно ли просто "f5"?)
int main(int argc, char *argv[]) {
int e = 5, f = 4;
printf("f6 = %i \n", f6(e, f, f5) );
return 0;
};
(но так не получается объявлять в main f5 и f6, если их текст пишу ниже main, то есть всегда удобнее, чтобы main была внизу?)
Оба варианта в вопросе являются полностью правильными
Разберём первый, там станет понятно:
Строчки:
int f1(int, int);
int f2(int x1, int x2, int (* pointer_to_f1)(int, int));
объявляют 2 прототипа (которые обычно принято писать вне определения функций)
И мы даём «обещание»:
«Где-нибудь позже (или раньше) в коде я дам определение этой функции»
Далее в коде:
int (*p_f1) (int, int);
p_f1 = f1;
Объявляется и инициализируется указатель на функцию (то есть это переменная, занимающая в памяти 2 или 4 байта (в зависимости от архитектуры и компилятора), и она хранит адрес, по которому можно обратиться к функции)
Сперва мы объявляем по синтаксису:
возвращаемый_тип (*имя_указателя)(типы_аргументов)
А потом инициализируем:
p_f1 = f1;
// ^ из-за того что мы указали без скобок ( f1() ), мы получим адрес функции
Лично я, когда хочу получить адрес функции, обычно добавляю &
перед названием (в данном случае будет &f1
(означает одно и тоже))
Ну а указатель на функцию в строчке:
printf("f2 = %i \n", f2(a, b, p_f1) );
мы передаём как любой другой указатель
и мы можем передовать указатель на функцию напрямую без p_f1
:
printf("f2 = %i \n", f2(a, b, f1) );
// ^ или &f1, одно и тоже
Что касается вызова такой функции, то через указатель можно вызвать функцию так:
(*имя_указателя)(параметры)
либо можно вызвать также, как мы вызываем настоящую функцию:
имя_указателя(параметры)
Все вышеперечисленное допустимо и не является ошибкой или особенностью, которую поддерживает, например, только gcc