17
foo();

(*foo)();

(&foo)();

これらの関数呼び出しの違いは何ですか (foo()どこかで定義されていると仮定します)? また、ある状況が別の状況で使用される可能性がある状況はありますか?

また、なぜ働かない&foo()*foo()ですか?

4

6 に答える 6

25

実際の呼び出し自体に違いはありません (むしろ、foo()宣言方法に応じてすべて同じことを行います) 。

C および C++ でのすべての関数呼び出しは、関数呼び出しの括弧の前に現れる関数ポインター式を介して行われます。必要に応じて、非ポインター型の暗黙的なアドレス オブ プロセスが行われます。

これは、C++ での動作を示すイデオンです。

&foo()and*foo()が機能しない理由は、関数呼び出し演算子がand()よりも優先されるためです。したがって、戻り値で何をしていたかによっては、機能する可能性があります。 戻り値のアドレスを取得し、それを逆参照します。状況によっては、これらの操作のいずれか、または両方が有効な場合があります。ポインタへの参照型を返す関数を考えてみましょう。*&&foo()*foo()

R..のコメントから取られたこの回答の一部。

于 2012-08-20T13:38:01.713 に答える
10

あなたは正確に何fooであるかを言いませんが、私はそれが関数であると仮定します.

これらの関数呼び出しの違いは何ですか?

明らかに、最初は通常の構文を使用して関数を呼び出します。

3 番目は関数のアドレスを取得し、それを呼び出そうとします。この言語では、関数ポインターを、それらが指す関数であるかのように呼び出すことができるため、これは と同等foo()です。

2 番目は、関数の逆参照を試みます。逆参照にはポインターが必要であり、言語では関数からその関数へのポインターへの暗黙的な変換が許可されているため、これは と同等であり、これは(*(&foo))()と同等foo()です。

要約すると、3 つすべてが同じことを行います。

また、ある状況が別の状況で使用される可能性がある状況はありますか?

コードを不必要な象形文字で装飾したくない場合を除き、関数または関数ポインターのいずれかに最初の形式以外を使用する理由はありません。

また、なぜ働かない&foo()*foo()ですか?

&(foo())優先順位規則は、これらがおよび と同等であることを意味し*(foo())ます。つまり、関数を呼び出し、アドレスを取得して結果を逆参照しようとします。関数に戻り値の型がある場合、最初の形式は「機能」します。2 つ目は、ポインタまたは (C++ では) オーバーロードされた unary を含む何かを返す場合に「機能」しますoperator*()

于 2012-08-20T13:49:24.203 に答える
0

が関数指定子の場合foo、これらはすべてCで同等です。

foo();
(foo)();
(*foo)();
(***foo)();
(*&foo)();
于 2012-08-20T13:59:26.093 に答える
0

foo() は関数 foo を呼び出します。

void foo() {return;}
foo();

(*foo)() は、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;
}

それが役に立ったことを願っています。

于 2012-08-20T13:46:54.993 に答える
0

これはタグ付け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;
}      
于 2012-08-20T14:39:53.197 に答える
0
foo();

という名前の関数を呼び出しますfoo

(*foo)();

という名前の関数へのポインターを介して関数を呼び出しfooます。これは通常、パラメータとして別の関数 ( callbackとも呼ばれます)に渡された関数を呼び出すときに表示されます。

/**
 * 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

括弧が重要であることに注意してください。関数呼び出し演算子()は unary よりも優先順位が高い*ため、式*foo()は「呼び出して結果を逆参照する」と解釈されますfooが、(*foo)()は「逆参照して結果を呼び出す」と解釈されfooます。

(&foo)();

は と同じことを行いますが、ポインターではなく参照(*foo)();を使用する点が異なります (C++ のみ)。繰り返しますが、括弧は重要です。は、「結果のアドレスを呼び出して取得する」と解釈されますが、これは合法ではありません。 &foo()foo

于 2012-08-20T14:21:25.547 に答える