int f(void);
引数を取らず、結果f
を返す関数として宣言しますが、int
int f();
f
固定されているが指定されていない数と型の引数を取る (そしてもちろん結果を返す) 関数として宣言しint
ます。
そのような宣言が与えられた場合、実際にパラメーターを定義する定義がどこかになければなりません。パラメータを取らない場合は、次のように定義できます。
int f() {
return 42;
};
2 つのパラメータを取る場合はint
、次のように定義できます。
int f(int x, int y) {
return x + y;
}
どちらの定義も と互換性がありますint f();
が、最初のものだけが と互換性がありint f(void)
ます。
パラメーターの型を指定する関数宣言、または特殊なケースとしてvoid
キーワードを使用してパラメーターがないことを指定する関数宣言は、プロトタイプです。古いスタイルの宣言など、これを行わない関数宣言。int f();
プロトタイプをサポートしていない数十年前の ANSI 以前のコンパイラを使用している場合や、非常に古いコードを維持していて、それを更新する時間や他のリソースがない場合を除き、使用しない理由はありません。プロトタイプ。プロトタイプを表示せずに関数を呼び出す場合でも、正しい数と型の引数を渡す必要があります。違いは、呼び出しが正しくないかどうかをコンパイラが判断できないことです。
(変数の数と型の引数を取る関数を定義できますprintf
。これはその例です。これは, ...
表記法を使用して行われます。関数自体は<stdarg.h>
、引数を処理するために で定義された機能を使用します。しかし、それは宣言とは関係ありません。あなたの質問に示されています。)
廃止された古いスタイルの関数宣言と定義を使用した小さなプログラムを次に示します。
#include <stdio.h>
#include <stdlib.h>
int add();
int main(argc, argv)
int argc;
char **argv;
{
if (argc == 3) {
/* NOTE: atoi() does no error checking */
printf("sum = %d\n", add(atoi(argv[1]), atoi(argv[2])));
}
else {
fprintf(stderr, "Usage: %s x y\n", argv[0]);
exit(EXIT_FAILURE);
}
}
int add(x, y)
int x, y;
{
return x + y;
}
add(1, 2, 3, 4)
orを書いた場合add("foo", "bar")
、コンパイラはエラーをキャッチしなかったことに注意してください。プログラムは単に誤動作したでしょう。
以下は、最新の関数宣言と定義を使用した同等のプログラムです。
#include <stdio.h>
#include <stdlib.h>
int add(int x, int y);
int main(int argc, char **argv) {
if (argc == 3) {
/* NOTE: atoi() does no error checking */
printf("sum = %d\n", add(atoi(argv[1]), atoi(argv[2])));
}
else {
fprintf(stderr, "Usage: %s x y\n", argv[0]);
exit(EXIT_FAILURE);
}
}
int add(int x, int y) {
return x + y;
}
可視プロトタイプは、コンパイラが不正な呼び出しを診断できることを意味します。