私の質問はとても簡単です。
通常、変数を宣言するときは、次のように変数の前にその型を置きます。
_int a;
_
関数ポインタは、2つの整数を取り、整数を返す関数をポイントする場合、int(*)(int,int)
のような型を持つことができます。しかし、そのようなポインターを宣言するとき、その識別子は次のように型の後ではありません:
_int(*)(int,int) mypointer;
_
代わりに、中央に識別子を記述する必要があります。
_int(*mypointer)(int,int);
_
これはなぜですか?申し訳ありませんが、それは恥ずかしいほど簡単な質問です...
返信してくれてありがとう。なので。
配列、ポインター、および関数のC構文がこのように設計されたのはなぜですか? に対する答えでこれを説明します。
言語の作成者は、構文を型中心ではなく変数中心にすることを好みました。つまり、プログラマーに宣言を見て、「式
*func(arg)
を書くとint
になります;*arg[N]
と書くと「func
」ではなく「float」があります-thisを取り、that "を返す関数へのポインタでなければなりません。WikipediaのCエントリ は次のように主張しています:
リッチーのアイデアは、使用法に似たコンテキストで識別子を宣言することでした。「宣言は使用法を反映しています」。
... K&R2のp122を引用。
この構造は、通常の関数の宣言方法(および使用方法)を反映しています。
通常の関数定義を考えてみましょう:
int foo (int bar, int baz, int quux);
次に、同じシグネチャの関数への関数ポインターを定義することを検討してください。
int (*foo) (int, int, int);
2つの構造が相互にミラーリングする方法に注目してください。 *foo
他の何かとしてではなく、関数ポインタとして識別するのがはるかに簡単です。
関数(関数へのポインタではない)を扱っている場合、名前も中央にあります。 return-type function-name "(" argument-list ")" ...
のようになります。たとえば、int foo(int)
では、int
が戻り型、foo
が名前、int
が引数リストです。
関数へのポインタはほぼ同じように機能します。戻り値の型、名前、引数リスト。この場合、_*
_を追加してポインターにし、(ポインターの_*
_が接頭辞であるため)括弧のペアを使用して_*
_を名前にバインドする必要があります戻り型の代わりに。たとえば、int *foo(int)
は、intパラメータを受け取り、intへのポインタを返すfooという名前の関数を意味します。代わりにfoo
にバインドされた*を取得するには、int (*foo)(int)
を与える括弧が必要です。
これは、関数へのポインターの配列が必要な場合に特に見苦しくなります。このような場合、ほとんどの人はポインター型にtypedefを使用し、その型の配列を作成するのが最も簡単だと感じています:
_typedef int (*fptr)(int);
fptr array[10];
_
私はいくつかの場所で関数ポインタが
int (*foo) (int a, int b);
また、いくつかの場所ではa
とb
が言及されておらず、両方とも機能しています。
そう
int (*foo) (int, int)
正しいです。
私が覚えていることがわかった非常に簡単な方法は、次のとおりです。
関数が次のように宣言されているとします:
int function (int a , int b);
Step1:関数を括弧で囲んでください:
int (function) (int a , int b);
Step2:*
関数名の前にあり、名前を変更します。
int (*funcPntr) (int a , int b);
PS:この回答では、命名規則などの適切なコーディングガイドラインに従っていません。