2013-10-27 4 views
8

私はこれらの2つのテスト機能を持っています。これらの関数ポインタはどちらもC/C++では合法なのですか?

int apply_a(int (*fun)(int, int), int m, int n) { 
    return (*fun)(m,n); 
} 

int apply_b(int (*fun)(int, int), int m, int n) { 
    return fun(m,n); 
} 

彼らは別の何かを返すように見えるので、なぜそれらの両方が同じ結果を得ていますか?

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

int res_a = apply_a(add, 2, 3); // returns 5 
int res_b = apply_b(add, 2, 3); // returns 5 

私は、それらのうちの1つがポインタアドレスまたはポインタ自体を返すと仮定しました。ポインターに格納されている値ではなく...

だからこそこれはなぜですか?

+2

を。 2番目のケースはコールです(カッコで渡されたパラメータで渡せます)。 – StoryTeller

+10

いずれも良いことではありません。 3つ星のプログラマになるには '(*** fun)(m、n)'を使うべきです。 –

答えて

7

C++は非メンバ関数のアドレスを扱い、それらのポインタを使用する際に構文的な砂糖を提供するためです。いずれかのコールは、そのようなポインタを使用するためのシンタックスシュガーもあり

int (* someFuncPtr)(int) = &someFunc; 

:どちらかと

int someFunc(int); 

int (* someFuncPtr)(int) = someFunc; 

または

一つは、このような関数のアドレスを取得することができます次の機能を備えています。

(*someFuncPtr)(5); 

または簡略化された構文を有する:機能のCとC++名で

someFuncPtr(5); 
+0

同じことが静的クラスのメソッドにも当てはまることを覚えておいてください。少なくともVisual C++ 2012ではこれをチェックしました;) – altariste

+0

これもC言語にも当てはまりますか?またはC++のための砂糖ルールですか? –

+0

C++は "function"型の別の表記法を導入しています。 'int(int)'は 'int(*)(int)'に変換可能です。 'someFunc'は' int(int) '型ですが、'&someFunc'は 'int(*)(int)'型です。 –

0

はまた、機能コードへのポインタです。任意のポインタとして、*を使用して逆参照することができます。関数ポインタの場合は、逆参照に加えて関数の呼び出しを意味します。apply_aの場合のように、それらの後ろに小文字を使用します。しかし、CとC++関数の有効な呼び出しは、単に名前で呼び出すことです。つまり、apply_bの場合です。

+0

名前ではありません。 **関数名ではなく、関数である**式は関数へのポインタに変換されます。 –

1

これは、これらの値のメモリアドレスを返さないためです。 ポインタを使用して関数を呼び出しても、関数を呼び出す値は変わりません。あなたが行うことができますが、変数に値を戻し、それはのようなメモリアドレスのgetです:

int result = fun(m,n); 
cout << "the result " << result << " pointing at " << &result << endl; 
6

(*fun)(m,n)することは、関数へのポインタに関数を変換するCおよびC++の規則にfun(m,n)と同じです。

2011年のルールは、6.3.2.1節です。「関数指定子は、関数型の式です。それはオペレータ _Alignof のsizeofオペレータ、のオペランドであるか、または単項&オペレータ、型の関数指定子は、「タイプを返す関数」を」ポインタを入力した式に変換される場合を除き関数 "を返します。 C++では、ルールは4.3節です。

ファンクションデジグネータは単なるファンクションの名前を示す識別子ではありません。それは識別子でも、別の表現でもかまいません。例えば、fooが関数の名前であれば、それは上記の関数へのポインタに自動的に変換されます。そして、fooは関数へのポインタなので、*fooが関数です。これは、あなたが書くことができることを意味:

(*fun)(m,n) 

結果はfunが自動的にポインタに変換されていることで、その後、*は、関数に評価され、その後、*funはポインタに変換され、その関数が呼び出されます。あなたはこれを続けて書くことができます:

(**************fun)(m,n) 

これはfun(m,n)と同じです。各*は再び関数を生成しますが、コンパイラはそれを自動的にポインタに戻します。あなたはこの戦いを永遠に続けることができますが、コンパイラは常に勝つでしょう。実際に

、これら全ては同じ効果があります(アスタリスクの有無にかかわらず)構文のいずれかがポインタを通じて関数を呼び出すために有効となっているので

(&fun)(m,n) 
(fun)(m,n) 
(*fun)(m,n) 
関連する問題