Почему указатель на функцию вызывается без разыменования? - PullRequest
1 голос
/ 03 июня 2009

У меня есть странный оператор typedef в программе на C ++, сгенерированный Py ++.

double radius(int);  // function to be wrapped
typedef double (*radius_function_type)(int);    
bp::def("radius", radius_function_type(&radius));   // bp::def is a function for wrapping

На данный момент я выяснил, что приведенное выше typedef statemnt не того типа, с которым большинство из нас знакомо,

typedef complex_type simple_alias;

Скорее, это способ объявления указателя на функцию, которая принимает int в качестве аргумента и возвращает double (то же, что и в прототипе). Итак, мой вопрос сейчас заключается в том, как получить указатель на функцию (без разыменования) be с именем с адресом функции как аргумент? Это также не соответствует прототипу. Кто-нибудь, пожалуйста, объясните!

Ответы [ 5 ]

6 голосов
/ 03 июня 2009

Не объявляется переменная указателя функции, но указатель функции typedef называется radius_function_type. radius_function_type(&radius) является просто (избыточным) приведением для самого указателя функции. (Унарный оператор & address-of также избыточен; для функции radius и &radius - это одно и то же.)

На низком уровне вызов функции - это просто размещение аргументов где-то в соответствии с базовым соглашением о вызовах (обычно в стеке), а затем переход к адресу памяти. Таким образом, компилятор может вызывать функцию только с указателем, если он знает тип указателя функции (сигнатура функции) и само значение указателя.

3 голосов
/ 03 июня 2009

Ваш вопрос сбивает с толку. Вы спрашиваете, что это делает:

radius_function_type(&radius)"

Это просто тип C ++, похожий на:

radius (int (42));

но так как радиус уже имеет тип radius_function_type, то вы можете так же легко сделать:

bp::def("radius", radius);

но поскольку это код, сгенерированный Py ++, он, вероятно, очень осторожен с выводом.

2 голосов
/ 03 июня 2009

Ну ... Это немного похоже на то, как массивы связаны с указателями в C и C ++. Имя функции также является в основном указателем. С этой точки зрения неудивительно, что с учетом определения:

int foo(int a, int b)
{
  return a + b;
}

Вы можете сделать вызов либо напрямую, через указатель, который является именем функции:

foo(1, 2);

или путем сохранения этого значения в отдельной переменной, которая должна быть объявлена ​​как указатель:

int (*pointer)(int, int) = foo;
pointer(1, 2);

В этом случае мы можем напрямую вызывать переменную-указатель, и нет необходимости явно «брать адрес» функции, написав &foo.

1 голос
/ 03 июня 2009

Указатель на функцию - это, в основном, адрес функции, которую нужно вызвать. Чтобы вызвать функцию, указанную указателем на функцию, вы рассматриваете указатель на функцию, как если бы это было имя функции, которую вы хотите вызвать. Сам акт вызова вызывает разыменование; нет необходимости в явном разыменовании.

Синтаксис указателя на функцию может выглядеть как указатель (с символами & и *) или также может быть опущен. Как уже указывалось @ unwind , это похоже на то, как обрабатываются массивы, когда пустой массив похож на указатель, и при желании вы можете использовать префикс & для получения адреса.

1 голос
/ 03 июня 2009

Разыменование (как вы думаете) указателя функции означает: доступ к памяти КОДА, как к памяти ДАННЫХ.

Указатель на функцию не может быть разыменован таким образом. Вместо этого это называется.

Я бы использовал имя «разыменование» рядом с «вызовом». Все в порядке.

В любом случае: C спроектирован таким образом, что как идентификатор имени функции, так и указатель на функцию, содержащая переменную, означают одно и то же: адрес в памяти CODE. И это позволяет перейти к этой памяти с помощью синтаксиса call () либо по идентификатору, либо по переменной.

...