#c #function #function-pointers #function-call
#c #функция #указатели на функции #функция-вызов #функции-указатели #вызов функции
Вопрос:
Итак, возьмите следующий код, я читал несколько конспектов лекций по указателям на функции, и я наткнулся на это:
int (*Convert(const char code))(int, int) {
if (code == ‘ ’) return amp;Sum; // Takes two ints, and adds
if (code == ‘-’) return amp;Difference; // Takes two ints, and subtracts
}
int main () {
int (*ptr)(int,int);
ptr = Convert(‘ ’);
printf( “%dn”, ptr(2,4));
}
Обычно я привык видеть что-то подобное при вызове функции, которая возвращает указатель на функцию, и для меня это имеет смысл, поскольку у меня есть все параметры, изложенные здесь char
, и два int
:
Convert('-')(5, 6);
Но из-за того, как это было написано в заметках, я не могу по-настоящему понять, что именно здесь происходит. Может кто-нибудь рассказать, как именно это работает? Связано ли это с присвоением (*ptr)(int, int)
адреса функции или что-то в этом роде?
Комментарии:
1. Это должно было вызвать у вас головную боль. Ничего, что нельзя было бы исправить с помощью typedef , всегда что-то, что вы хотите сделать с типами указателей на функции. Используйте
typedef int (*converter)(int left, int right);
. Теперь он становится читаемым вместо lisp: конвертер Convert(const char code) {…}
Ответ №1:
Может кто-нибудь рассказать, как именно это работает? Связано ли это с присвоением (* ptr)(int, int) адреса функции или что-то в этом роде?
Функция Convert()
возвращает указатель на функцию — либо указатель на Sum()
, либо указатель на Difference()
, в зависимости от ее аргумента (или она завершается без указания возвращаемого значения, что является плохой новостью для вас, если вы вообще что-либо делаете с возвращаемым значением). Этот указатель на функцию хранится в переменной ptr
, которая объявлена как имеющая тот же тип, Convert()
что и returns . Затем указанная функция может быть вызвана с помощью оператора вызова функции, ()
.
Возможно, это было бы немного понятнее, если бы было переписано таким эквивалентным образом с использованием typedef
:
typedef int (*op_function)(int, int);
op_function Convert(const char code) {
if (code == ‘ ’) return amp;Sum; // Takes two ints, and adds
if (code == ‘-’) return amp;Difference; // Takes two ints, and subtracts
}
int main () {
op_function ptr;
ptr = Convert(‘ ’);
printf( “%dn”, ptr(2,4));
}
Ответ №2:
Либо есть опечатка, либо вы имеете в виду имя функции AddSub
вместо Convert
.
Например
int (*AddSub(const char code))(int, int) {
if (code == ‘ ’) return amp;Sum; // Takes two ints, and adds
if (code == ‘-’) return amp;Difference; // Takes two ints, and subtracts
}
[Примечание: обратите внимание на то, что использование оператора amp;
является избыточным из-за неявного преобразования обозначения функции в указатель на функцию, например
int (*AddSub(const char code))(int, int) {
if (code == ‘ ’) return Sum; // Takes two ints, and adds
if (code == ‘-’) return Difference; // Takes two ints, and subtracts
}
-конечная заметка.]
Итак, вызывая функцию, как
AddSub('-');
вы получите выражение типа указатель на функцию типа int( int, int ).
, и вы снова можете предоставить аргументы возвращаемому указателю, чтобы вызвать указанную функцию, например
AddSub('-')(5, 6);
Чтобы сделать его более понятным, вы можете переписать приведенное выше выражение следующим образом
( AddSub('-') )(5, 6);
Это то же самое, что и этот фрагмент кода
int ( *ptr )( int, int ) = AddSub(‘ ’);
printf( “%dn”, ptr(2,4));
но без промежуточной переменной ptr
.
printf( “%dn”, AddSub( ' ' )(2,4) );
Ответ №3:
Указатели на функции сохраняют ссылку на функцию и могут быть вызваны, но они ведут себя точно так же, как и другие указатели. Синтаксис многих людей сбивает с толку, и это одно из мест, где скрытие указателей за typedefs имеет смысл, но в этом нет необходимости
#include <stdio.h>
#include <stdlib.h>
typedef int func(int, int);
int Difference(int a, int b){
return a - b;
}
int Sum(int a, int b){
return a b;
}
func *Convert(const char code) {
if (code == ' ') return Sum; // Takes two ints, and adds
if (code == '-') return Difference; // Takes two ints, and subtracts
}
int main () {
func *ptr;
ptr = Convert(' ');
printf( "%dn", ptr(2,4));
}