2012-06-24 31 views
5

関数呼び出し

void f(void){ 
    puts("OK"); 
} 

int main(void){ 
    f(); 
    (*f)(); 
    (&f)(); 

    return 0; 
} 

第一第二の関数ポインタを逆参照するためのセマンティックであるFを呼び出すための標準的な方法、

あり、

3番目の例では、&演算子を関数名に適用していますが、正常に動作しているようです。

2番目と3番目のケースではどうなりますか?

ありがとうございました。

+1

関数へのポインタは、第三中のコールのために逆参照されます。 –

+5

お楽しみのために '(********** f)();'も同様に – Flexo

+0

誰かが2番目と3番目の呼び出しを使用する必要があるかどうかを質問しています... –

答えて

8

関数呼び出しは、です。関数ポインタを介して実行されるのは、常にです。 C99セクション6.5.2.2から:

呼び出された関数を表す式は、関数へのポインタ型を持ちます。

しかし、ほとんどの場合、関数型は関数ポインタ型に崩壊します。 C99セクション6.3.2.1から:

それはsizeofオペレータや タイプ「タイプを返す関数」と単項&演算子、関数指定子の オペランドが持つ式に変換されている場合を除きタイプ " 関数へのポインタタイプを返す"。

だからあなたの3つの呼び出しは、このように評価されます。

(&f)(); 
(&(*(&f)))(); 
(&f)(); 

すべてが有効です。しかし明らかに、最初のもの(f())が最もきれいで読みやすい。

+0

なぜ(&( &f)())valid.When&fが関数ポインタ型に崩壊したら? – Raulp

+0

@softy: '&f'は**すでに**関数ポインタ型です。したがって、 '&& f'は関数ポインタポインタ型です。 –

+6

@OliCharlesworth - '&f'はr値なので、別の'& '単項演算子の引数にすることはできません。 – rodrigo

1

2番目のケースでは、関数ポインタを使用しています。関数ポインタは、関数への参照を暗記するために使用され、呼び出しのどこかで呼び出すことができます。通常、コールバックの実装に使用されます。 関数へのポインタを格納している場合は、最初の表記を使用する必要があります。

私は1番目と3番目のものは同等だと思います。 あなたが関数ポインタを宣言した場合、実際にあなたがそれを初期化することができ、次の両方の方法は:

void AFunction(); 
void (*funcPtr)() = NULL; 

funcPtr = AFunction; 
funcPtr = &AFunction; 
関連する問題