そのコードに対して警告が表示されない場合は、コンパイラが C99 規則を適用していないことが原因です (printf
目に見える宣言なしで や任意の関数を呼び出すと、制約違反になります)。適切なオプションをコンパイラに渡すことで、おそらく少なくともいくつかの警告を受け取ることができます。gcc を使用している場合は、 を試してくださいgcc -std=c99 -pedantic -Wall -Wextra
。
1978 年のカーニガンとリッチーの古典的な本The C Programming Languageの第 1 版で記述された、いわゆる K&R C には、関数プロトタイプがありませんでした。(プロトタイプは、そのパラメーターの型を指定する関数宣言です。) 関数定義は依然としてそのパラメーターを (おそらく暗黙的に) 定義する必要がありましたが、宣言はそうではありませんでした。関数呼び出し) パラメータへ (関数定義内)。
間違った数や引数の型で関数を呼び出した場合に何が起こるかは、完全には明確ではありませんでした。現代的に言えば、これは未定義の動作でしたが、古いコンパイラでは通常、トリックを実行できます。
1989 ANSI C 標準 (1990 ISO C 標準として再発行) では、プロトタイプ (初期の C++ から借用) が導入されましたが、それらは必須ではありませんでした。しかし、間違った数またはタイプの引数で関数を呼び出すと、未定義の動作が発生することが明示的に述べられていました。コンパイラはそれについて警告する必要はありませんが、プログラムを実行すると、文字通り何でも実行できます。
1999 年の ISO C 標準では、"implicit int" ルールが廃止され、可視宣言なしで関数を呼び出すことは違法 (制約違反) になりましたが、古いスタイルの関数宣言と定義は引き続き許可されていました。したがって、K&R1 および C89/C90 ルールの下では、関数定義は次のようになります。
int func(param111)
{
printf("%d\n", param111);
return param111;
}
は有効で、param111
タイプはですint
。C99 ルールでは無効ですが、これは次のとおりです。
int func(param111)
int param111;
{
printf("%d\n", param111);
return param111;
}
はまだ合法です (2011 規格の下でも合法です)。
C99 および C11 の時点で、目に見える宣言がプロトタイプではない関数を呼び出す場合、引数を正しく取得するのは完全にあなた次第です。コンパイラは、間違った場合に警告する必要はありません。
これが、すべての関数の宣言と定義に常にプロトタイプを使用する必要がある理由です。ANSI 以前のコンパイラでコンパイルするコードを書く必要は、最近ではほとんどありません。少なくとも C89/C90 をサポートしていないコンパイラを見つけるのは困難です。
ああ、追加する必要があります
#include <stdio.h>
を呼び出しているため、ソース ファイルの先頭にprintf
. C89/C90 規則ではprintf
、可視宣言なしで呼び出した場合の動作は未定義です (printf
可変数の引数を取るため)。C99 以降では、これは制約違反であり、コンパイル時の診断が必要です。
欠落しているパラメーター宣言について、私はつまらないことをしてきました。プログラムのわずかに変更されたバリアント:
#include <stdio.h> /* add this line */
int func(param111)
int param111; /* add this line */
{
printf("%d\n", param111);
return param111;
}
int main(void) /* add "void" */
{
int bla0 = func(99);
int bla1 = func(10,99);
int bla2 = func(11111110,99,10001);
printf("%d, %d, %d\n", bla0, bla1, bla2);
}
C90、C99、または C11 でコンパイル時の診断を必要とする規則に違反していませんが、2 番目と 3 番目の呼び出しのfunc
動作は未定義です。
func
コンパイラには、呼び出しが正しくないことを警告するのに十分な情報が実際にあることに注意してください。の定義を見ただけでfunc
、暗黙的に変換可能な型の引数を 1 つだけ渡さない呼び出しint
は無効であることを認識しているはずです。警告は必要ありませんが、コンパイラはいつでも必要な追加の警告を表示できます。どうやら gcc (および使用しているコンパイラ) の作成者は、古いスタイルの宣言および/または定義を使用した関数の呼び出しの不一致について警告する努力をする価値がないと感じていたようです。