web-dev-qa-db-ja.com

引数が多すぎるポインタを介して関数を呼び出すことができるのはなぜですか?

私がこの機能を持っているとしましょう:

int func2() {
    printf("func2\n");
    return 0;
}

今、私はポインタを宣言します:

int (*fp)(double);

これは、double引数を取り、intを返す関数を指している必要があります。

func2引数はありませんが、それでも私が書くとき:

fp = func2;
fp(2);

2は任意の数です)、func2`は正しく呼び出されます。

何故ですか?関数ポインタに対して宣言するパラメータの数に意味はありませんか?

23
yotamoo

はい、意味があります。 Cでは(ただし、C++ではnot)、空の括弧のセットで宣言された関数は、nspecifiedの数のパラメーターを受け取ることを意味します。これを行うと、コンパイラが引数の数とタイプをチェックできなくなります。これは、C言語がANSIおよびISOによって標準化される前からの遺物です。

適切な数とタイプの引数を使用して関数を呼び出さないと、未定義の動作になります。代わりに、voidのパラメーターリストを使用してゼロパラメーターを取るように関数を明示的に宣言すると、間違ったタイプの関数ポインターを割り当てると、コンパイラーは警告を出します。

int func1();  // declare function taking unspecified parameters
int func2(void);  // declare function taking zero parameters
...
// No warning, since parameters are potentially compatible; calling will lead
// to undefined behavior
int (*fp1)(double) = func1;
...
// warning: assignment from incompatible pointer type
int (*fp2)(double) = func2;
46
Adam Rosenfield