55

私の質問は非常に単純なものです。

通常、変数を宣言するときは、次のようにその型を前に置きます。

int a;

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

int(*)(int,int) mypointer;

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

int(*mypointer)(int,int);

これはなぜですか?すみません、恥ずかしいほど簡単な質問だと思います...

返信してくれてありがとう。なので

4

4 に答える 4

32

これについては、配列、ポインター、関数のC構文がこのように設計された理由について説明します。、そしてそれは基本的に次のようになります:

言語の作者は、構文を型中心ではなく変数中心にすることを好みました。つまり、プログラマーに宣言を見て、「式を書くと、*func(arg)結果はint;*arg[N]になります。書くと、floatが必要になる」ではなく、「これfuncを受け取る関数へのポインターでなければならない」と考えてもらいたいと考えていました。そしてそれを返す"。

ウィキペディアのCエントリは、次のように主張しています。

リッチーのアイデアは、識別子をその使用法に似たコンテキストで宣言することでした。「宣言は使用法を反映する」。

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

于 2013-01-01T22:22:06.033 に答える
24

この構造は、通常の関数がどのように宣言(および使用)されるかを反映しています。

通常の関数定義を考えてみましょう。

int foo (int bar, int baz, int quux);

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

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

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

于 2013-01-01T22:21:57.657 に答える
13

関数(関数へのポインターではない)を扱っている場合、名前も真ん中にあります。次のようになりますreturn-type function-name "(" argument-list ")" ...。たとえばint foo(int)、のintは、戻り値の型、foo名前、およびint引数リストです。

関数へのポインタはほとんど同じように機能します。つまり、タイプ、名前、引数リストの順に戻ります。この場合、*ポインタにするためにaを追加する必要があります。また、(*ポインタのforはプレフィックスであるため)*戻り型ではなく、名前にバインドするための括弧のペアを追加する必要があります。たとえばint *foo(int)、intパラメータを取り、intへのポインタを返すfooという名前の関数を意味します。代わりに*をバインドするfooには、かっこが必要 int (*foo)(int)です。

関数へのポインタの配列が必要な場合、これは特に醜くなります。このような場合、ほとんどの人は、ポインタ型にtypedefを使用してから、その型の配列を作成するのが最も簡単だと考えています。

typedef int (*fptr)(int);

fptr array[10];
于 2013-01-01T22:22:22.677 に答える