違い C 関数ポインター構文




ダブル ポインタ イメージ (4)

私の質問はとても単純です。

通常、いくつかの変数を宣言するときは、その前にその型を入れます:

int a;

関数ポインタは、2つのintをとり、intを返す関数を指す場合には、int(*)(int、int)のような型を持つことができます。 しかし、そのようなポインタを宣言するとき、その識別子は以下のように型の後にはありません:

int(*)(int,int) mypointer;

代わりに、識別子を中央に記述する必要があります。

int(*mypointer)(int,int);

なぜこれはそうですか? 申し訳ありませんが、わかりやすく簡単な質問です...

誰にも返信してくれてありがとう。 として


私はいくつかの場所で関数ポインタが

int(* foo)(int a、int b);

いくつかの場所では、aとbは言及されておらず、どちらもまだ動作しています。

したがって、int(* foo)(int、int)も正しいです。

私が覚えていることがわかったとても簡単な方法は、以下に述べるとおりです

関数が次のように宣言されているとします。int function(int a、int b); ステップ1 - 関数を単純にparanthasesに入れます:int(function)(int a、int b); ステップ2 - 関数名の前に*を置き、名前を変更します。int(* funcPntr)(int a、int b);

PS:私はこの答えで命名規則などの適切なコーディングガイドラインに従っていません。


関数(ポインタを指すポインタではない)を扱っている場合、その名前も真ん中にあります。 それは次のようになります: 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 bar, int baz, int quux);

次に、同じシグネチャの関数への関数ポインタを定義することを検討してください。

int (*foo) (int, int, int);

2つの構造が互いにどのように鏡像になっているかに注目してください これにより、 *foo他のものではなく関数ポインタとして識別するのがずっと簡単になります。


私はこれを私の答えで説明します。配列、ポインタ、および関数のC構文がこのように設計されたのはなぜですか? それは基本的に次のようになります。

言語作成者は、型中心型ではなく変数型中心型を使用することを推奨しました。 つまり、プログラマは宣言を見て、「式*func(arg)を書くとintなります」と書いた場合、「 *func(arg) *arg[N] " funcこれを受け取り、それを返す関数へのポインタでなければなりません"。

WikipediaCのエントリには次のように書かれています:

Ritchieのアイデアは、その使用法に似た文脈で識別子を宣言することでした。「宣言は使用を反映します」。

... K&R2のp122を引用しています。





declare