2012-02-16 27 views
3

これら2宣言の違いは何ですか:C関数ポインタの混乱

int operate(int (*func)(int, int), int a, int b){ 
    return (*func)(a, b); 
} 

int operate(int func(int, int), int a, int b){ 
     return func(a, b); 
} 

これら二つも同等であると思わ:operate(sum, 1, 1)operate(&sum, 1, 1)

私は関数を渡す場合は、 sumは、funcの代わりに2つの数字の関数として、結果は同じです。どうして?

答えて

4

§6.7.5.3/ 8「」関数復帰型「として

パラメータの宣言」6.3のように、「」タイプを返す関数へのポインタ「」に調整しなければなりません。 2.1。

つまり、2つの関数宣言は同じです。

限り関数呼び出しが進むにつれて、§6.5.2.2/ 3:

括弧(続く後置式)式の空の場合も、カンマ区切り リストを含む関数呼び出しです。後置式は呼び出された関数を表します。

func(a, b);(*func)(a, b)は両方とも括弧で囲まれた後置式であるため、両方とも関数呼び出しです。 func(*func)はどちらも同じ関数を指定しているので、両方とも同じ関数を呼び出します。

3

2つの関数プロトタイプは同等です。 C99から6.7.5.3:

6.3.2.1のように、 "関数の戻り値の型"としてのパラメータの宣言は、 "関数の戻り値の型へのポインタ"に調整されます。

2つの関数呼び出し(operate(sum, 1, 1)operate(&sum, 1, 1))は同等です。関数はほとんどのコンテキストで関数ポインタに減衰します(配列が最初の要素へのポインタにどのように崩壊するかと同様)。 C99から6.3.2.1:

関数指定子は、関数型を持つ式です。 sizeof演算子のオペランド または単項演算子&を除いて、 タイプの '関数戻り値型'を持つ関数指定子は、型 ''ポインタ ' 関数戻り値型'を持つ式に変換されます。

+0

崩壊についての第2段落は、外れていると思います。あなたが '(* func)'を関数として数え、 'func'をそれが崩壊するポインタとして数えない限り、崩壊は起こっていません...? –

+0

@ R ..:そうです。私は '操作(合計、1,1)'と '操作(&合計、1、1)'を指していました。 –

+0

ああ、私は今.. –