В чем разница между вызывающими функциями следующим образом?
foo();
(*foo)();
(&foo)();
В чем именно заключается разница между этими вызовами функций (если предположить, что foo()
где-то определено)? и есть ли ситуации, когда можно было бы использовать другую?
Также, почему не работают &foo()
и *foo()
?
Ответы
Ответ 1
Нет никакой разницы между фактическими вызовами (скорее, все они будут делать то же самое в зависимости от того, как объявлен foo()
)
Все вызовы функций в C и С++ выполняются с помощью выражения-указателя функции, которое появляется перед круглыми скобками функций. При необходимости имеет место неявный адрес не указательных типов.
Здесь идеал, демонстрирующий поведение на С++.
Причина &foo()
и *foo()
не работает, так как оператор вызова функции ()
имеет приоритет над *
и &
. Таким образом, они могут работать, в зависимости от того, что вы делали с возвращаемым значением. &foo()
будет принимать адрес возвращаемого значения, а *foo()
будет разыменовывать его. В некоторых случаях любая из этих операций или и то, и другое могут быть законными. Рассмотрим функцию, возвращающую тип ссылки на указатель.
Часть этого ответа взята из комментария R..
Ответ 2
Вы не говорите точно, что такое foo
, но я буду считать его функцией.
В чем разница между этими вызовами функций?
Очевидно, что первая вызывает функцию, используя обычный синтаксис.
Третий берет адрес функции и пытается вызвать это; язык позволяет вызвать указатели на функции, как если бы они были функцией, на которую они указывают, поэтому это эквивалентно foo()
.
Вторая попытка разыменовать функцию. Для разыменования требуется указатель, и язык позволяет неявное преобразование из функции в указатель на эту функцию, поэтому это эквивалентно (*(&foo))()
, что в свою очередь эквивалентно foo()
.
Подводя итог: все три делают то же самое.
и есть ли ситуации, когда можно было бы использовать другую?
Если вы не хотите украсить свой код ненужными heiroglyphics, нет причин использовать что-либо, кроме первой формы, для любых функций или указателей функций.
Кроме того, почему не работают &foo()
и *foo()
?
Правила приоритета означают, что они эквивалентны &(foo())
и *(foo())
; то есть они вызывают функцию и пытаются принять адрес и разыменовать результат. Первая форма будет "работать", если функция имеет тип возврата; второй будет "работать", если он вернет указатель или (в С++) что-то с перегруженным унарным operator*()
.
Ответ 3
foo() вызывает функцию foo.
void foo() {return;}
foo();
(* foo)() dereferences a (function) указатель с именем foo и вызывает его с нулевыми аргументами.
void bar() {return;}
int main(int argc, char** argv){
void(*foo)() = &bar;
(*foo)(); // works
(*bar)(); // also works
return 0;
}
(& foo)() ссылается на функцию foo и вызывает ее с нулевыми аргументами.
void bar() {return;}
int main(int argc, char** argv){
(&bar)();
return 0;
}
Надеюсь, что это помогло.
Ответ 4
Если foo
является обозначением функции, все они эквивалентны в C:
foo();
(foo)();
(*foo)();
(***foo)();
(*&foo)();
Ответ 5
foo();
Вызывает функцию с именем foo
.
(*foo)();
Вызывает функцию с помощью указателя на функцию с именем foo
; вы обычно видите это при вызове функции, которая была передана в качестве параметра другой функции (также называемой обратным вызовом):
/**
* Execute the function pointed to by "foo" for each element
* in the array.
*/
void map(int *arr, size_t arrsize, void (*foo)(int))
{
size_t i;
for (i = 0; i < arrsize; i++)
(*foo)(arr[i]); // can also be called as foo(arr[i]);
}
void bar(int i)
{
printf("i = %d\n", i);
}
int main(void)
{
int arr[] = {1, 2, 3, 4, 5};
/**
* Call the function "bar" for each member
* of "arr".
*/
map(arr, sizeof arr / sizeof *arr, bar);
}
Отображение в этом примере выглядит глупо, но оно иллюстрирует концепцию. Так же, как вы можете иметь указатели на разные типы данных, вы можете иметь указатели на разные типы функций. Вместо выполнения функции с именем foo
мы выполняем функцию, на которую указывает foo
.
Обратите внимание, что круглые скобки важны: оператор вызова функции ()
имеет более высокий приоритет, чем унарный *
, поэтому выражение *foo()
будет интерпретироваться как "вызов foo
и разыменовать результат", тогда как (*foo)()
интерпретируется как "разыменование foo
и вызов результата".
(&foo)();
делает то же самое, что и (*foo)();
, за исключением того, что он работает через ссылку вместо указателя (только С++). Опять же, круглые скобки важны; &foo()
интерпретируется как "вызов foo
и берет адрес результата", что не является законным.
Ответ 6
Поскольку это помечено c++
, возможно, что функция вернет ссылку на этом языке, и такую функцию можно назвать &foo()
:
#include <iostream>
using std::cout;
using std::endl;
int & foo() {
static int f = 5;
return f;
}
int main() {
cout << foo() << endl;
*(&foo()) = 7;
cout << foo() << endl;
return 0;
}