foo();
(*foo)();
(&foo)();
これらの関数呼び出しの違いは何ですか (foo()
どこかで定義されていると仮定します)? また、ある状況が別の状況で使用される可能性がある状況はありますか?
また、なぜ働かない&foo()
の*foo()
ですか?
実際の呼び出し自体に違いはありません (むしろ、foo()
宣言方法に応じてすべて同じことを行います) 。
C および C++ でのすべての関数呼び出しは、関数呼び出しの括弧の前に現れる関数ポインター式を介して行われます。必要に応じて、非ポインター型の暗黙的なアドレス オブ プロセスが行われます。
&foo()
and*foo()
が機能しない理由は、関数呼び出し演算子がand()
よりも優先されるためです。したがって、戻り値で何をしていたかによっては、機能する可能性があります。 戻り値のアドレスを取得し、それを逆参照します。状況によっては、これらの操作のいずれか、または両方が有効な場合があります。ポインタへの参照型を返す関数を考えてみましょう。*
&
&foo()
*foo()
R..のコメントから取られたこの回答の一部。
あなたは正確に何foo
であるかを言いませんが、私はそれが関数であると仮定します.
これらの関数呼び出しの違いは何ですか?
明らかに、最初は通常の構文を使用して関数を呼び出します。
3 番目は関数のアドレスを取得し、それを呼び出そうとします。この言語では、関数ポインターを、それらが指す関数であるかのように呼び出すことができるため、これは と同等foo()
です。
2 番目は、関数の逆参照を試みます。逆参照にはポインターが必要であり、言語では関数からその関数へのポインターへの暗黙的な変換が許可されているため、これは と同等であり、これは(*(&foo))()
と同等foo()
です。
要約すると、3 つすべてが同じことを行います。
また、ある状況が別の状況で使用される可能性がある状況はありますか?
コードを不必要な象形文字で装飾したくない場合を除き、関数または関数ポインターのいずれかに最初の形式以外を使用する理由はありません。
また、なぜ働かない
&foo()
の*foo()
ですか?
&(foo())
優先順位規則は、これらがおよび と同等であることを意味し*(foo())
ます。つまり、関数を呼び出し、アドレスを取得して結果を逆参照しようとします。関数に戻り値の型がある場合、最初の形式は「機能」します。2 つ目は、ポインタまたは (C++ では) オーバーロードされた unary を含む何かを返す場合に「機能」しますoperator*()
。
が関数指定子の場合foo
、これらはすべてCで同等です。
foo();
(foo)();
(*foo)();
(***foo)();
(*&foo)();
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;
}
それが役に立ったことを願っています。
これはタグ付け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;
}
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