私は書き込もうとしています:
typedef int foo();
...
foo bar
{
return 1;
}
しかしerror C2206
、typedefは関数宣言に使用できないということがあります。このエラーの原因は何ですか? foo bar
としてコンパイルするだけでよいと思いますint bar()
。
この宣言:
typedef int foo();
完全に有効です。foo
type のエイリアスint()
、つまり「引数を返さint
ず引数を取らない関数」として定義します。
(余談: C は(void)
引数なしを示すために使用します。C++ は を使用します()
。この回答の以前のバージョンは C の規則に基づいていました。)
関数型ではなく、関数へのポインター型に対して typedef を定義する方が一般的ですが、どちらも有効です。上記の typedef を指定すると、関数ポインター オブジェクトを次のように宣言できます。
foo *funcptr;
ただし、typedef を使用して関数を宣言または定義することはできません。言語で許可されている場合は、関数を次のように宣言できます。
foo func; /* would be equivalent to "int func(void);" *if* it were legal */
また:
foo func { return 42; }; /* would be equivalent to
"int func(void) { return 42; }"
*if* it were legal */
これが便利な場合もあります。またはで定義された標準signal
関数には、かなり複雑な宣言があります。<signal.h>
<csignal>
void (*signal(int sig, void (*func)(int)))(int);
typedef
シグナル ハンドラの関数型に対してを定義できます。
typedef void (signal_handler)(int);
signal
次のように宣言できます。
void (*signal(int sig, signal_handler *func);
ただし、その typedef を使用して独自のシグナル ハンドラーを宣言または定義することはできません。ただし、これを使用してシグナル ハンドラー関数へのポインターを宣言することはできます。
signal_handler *funcptr = my_handler;
signal(SIGINT, funcptr);
qsort()
と で必要な関数ポインタ引数にも同じことが当てはまりますbsearch()
。
関数型の typedef を定義できるのに、それを関数の宣言または定義に使用できないのはなぜでしょうか?
深い理由はないと思います。言語がたまたまそれを許可していません。関数宣言の場合、1 つの問題は、
signal_handler foo;
オブジェクト宣言のように見えますが、代わりに関数を宣言します (別の場所で定義する必要があります)。そして、関数定義の typedef を許可します:
signal_handler foo { /* ... */ }
言語の文法を変更する必要があり、定義を見たときにパラメーターと戻り値の型を確認するのが難しくなります。また、関数定義は、宣言とは異なり、すべてのパラメーターに名前を付ける必要があるため、別のレベルの複雑さが追加されます。
しかし、本当の理由は、デニス・リッチーが C を設計したとき、C を考えていなかったか、価値があるとは考えていなかったからだと思います (そして、Stroustrup は C を変更する十分な理由を持っていませんでした。設計された C++)。
関数ポインタ typedef の宣言は次のとおりです。
typedef int (*foo)();
また、関数宣言に括弧がありません
foo bar()
{
return 1;
}
また1
、正当な関数ポインタ値ではありません。
foo bar()
{
return 1; // this line is an error
}