Подтвердить что ты не робот

В чем разница между вызывающими функциями следующим образом?

foo();

(*foo)();

(&foo)();

В чем именно заключается разница между этими вызовами функций (если предположить, что foo() где-то определено)? и есть ли ситуации, когда можно было бы использовать другую?

Также, почему не работают &foo() и *foo()?

4b9b3361

Ответ 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;
}