Как вызвать указатель на функцию без разыменования?

У меня есть странная инструкция typedef в программе на С++, сгенерированная 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 (то же, что и прототип). Итак, теперь мой вопрос заключается в следующем: как указатель на функцию (без разыменования) называется с адресом функции в качестве аргумента? Это также не соответствует прототипу. Кто-нибудь, пожалуйста, объясните!

Ответ 1

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

radius_function_type(&radius)"

Это просто код типа С++, немного похожий на:

radius (int (42));

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

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

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

Ответ 2

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

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

Ответ 3

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

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

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

foo(1, 2);

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

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

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

Ответ 4

Разыменование (как вы думаете) указатель функции означает: доступ к памяти CODE, так как это будет память DATA.

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

Я бы использовал имя "разыменование" рядом с "вызовом". Это нормально.

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

Ответ 5

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

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