2012-11-20 6 views
7

私は両方を試しました - CC++と両方とも正常です。関数ポインタを使用して関数を呼び出す - ポインタを逆参照するかどうか違いは何ですか?

私は関数ポインタにちょっと新たなんだと、ここで私を驚かせた簡単なコード、です:

#include <assert.h> 
void sort(int* arr, const int N); 

int main() 
{ 
    int arr1[] = { 1, 5, 2, 6, 2 }; 
    int arr2[] = { 1, 5, 2, 6, 2 }; 

    void (*sort_ptr)(int*, const int) = sort; 

    sort_ptr(arr1, 5); 
    (*sort_ptr)(arr2, 5); 

    assert(arr1[0] == 1 && arr1[1] == 2 && arr1[2] == 2 && 
      arr1[3] == 5 && arr1[4] == 6); 
    assert(arr2[0] == 1 && arr2[1] == 2 && arr2[2] == 2 && 
      arr2[3] == 5 && arr2[4] == 6); 

    return 0; 
} 

void sort(int* arr, const int N) 
{ 
    // sorting the array, it's not relevant to the question 
} 

をので、

sort_ptr(arr1, 5); 

(*sort_ptr)(arr2, 5); 

の違いは何だが、どちらもうまくいくようです(エラーも警告もソートされていません)、ちょっと混乱しています。どちらが正しいか、どちらが正しいですか?

答えて

15
sort_ptr(arr1, 5); 

(*sort_ptr)(arr2, 5); 

両方が正しいです。実際には、あなたが望む限り多くのアスタリスクを置くことができ、それらはすべて正しいです:機能の

(*****sort_ptr)(arr2, 5); 

名は、関数へのポインタに減衰します。したがって、繰り返し参照を解除すると、同じポインタが生成されます。

+0

なぜ*****好きなだけ多く説明できますか? – Omkant

+0

うわー、それは私には本当に不思議です。なぜ言語はこれを許すのだろうか? OK、私は1つの '*'を使っても問題ありません - 何らかの明示的/暗黙的逆参照(@Alsが彼の答えで述べたように)ですが、何故多くの '*'を許可するのでしょうか? –

+5

正式には、関数を呼び出すには関数へのポインタが必要です。関数は関数へのポインタを暗黙的に変換します。あなたが '*'を追加するたびに、結果は関数へのポインタに変換されます。関数へのポインタに変換され、さらに '*'が可能になります。 –

2

コンパイラに関する限り、sort_ptr(*sort_ptr)は同じです。しかし、sort_ptrが本当にポインタであれば、それを明示的に逆参照すると、読者にとってははるかに明確になります。一般に;関数へのポインタで関数を直接呼び出すことができるという事実があります:テンプレートでは、関数オブジェクトへのポインタを作る場所で、operator()()のクラスとまったく同じように動作します。

関連する問題