厳密準拠モード (「理論上」を意味する) では、スコープ内の関数のプロトタイプ宣言なしで可変数の引数を取る関数を呼び出すと、未定義の動作 (これは悪いことです) が呼び出されます。printf()
これは、プロトタイプ from#include <stdio.h>
または同等の宣言なしで使用するプログラムで、コンパイラが好きなことを何でもできることを意味します。「好きなもの」には、オプションの 1 つとして正しく動作することが含まれます。それはあなたの例で選択されたオプションのようです。
実際には、コードは、関数の正式な宣言がなくても、ほとんどの実用的なコンパイラで問題なく動作しprintf()
ます。
qrdlで指摘された通り、CコンパイラがCライブラリとリンクしているため、関数が見つかりました。
C99 と「implicit int」に関する Chris Young のコメントは正確ですが、「可変引数関数はスコープ内にプロトタイプを持たなければならない」という規則は C89 と C99 の両方に適用されることに注意してください。ほとんどのコンパイラは、デフォルトでは厳密な C99 互換モードでは動作しません。そのようにコンパイルできないコードが多すぎるためです。
クリス・ヤングは次のようにコメントしています。
明確にするために、私のコメントは暗黙の宣言を削除する C99 に関するものでした。「暗黙の int」と言うと、foo(void); などの宣言を許可する C89 の機能を参照していると思います。int foo(void); を意味する、C99 も削除されたもの。
もちろん、クリスは正しいです。C99 標準から削除された 2 つの「暗黙の宣言」機能がありました。標準の序文には、次のようにリストされています。
私は十分に明確に考えていませんでした(したがって書いていません)。それにもかかわらず、C89 と C99 の両方で、可変数の引数を取る関数のスコープ内にプロトタイプが必要です。
説明する:
extern int pqr();
int main(void)
{
int i = pqr(1, 3);
return i;
}
pqr()
最初の行がない場合、これは、 (指定されていない引数を使用して) 整数を返す関数として関数を暗黙的に宣言した正しい C89 フラグメントです。最初の行が で置き換えられた場合、これは整数を返す関数としてextern pqr();
明示的に宣言された正しい C89 フラグメント(引数は指定されていません) ですが、戻り値の型は 'implicit ' です。書かれているように、関数は明示的に宣言され、明示的な戻り値の型がありますが、未指定の引数があります。完全に望ましいわけではありませんが、これは有効な C99 だと思います。確かに、GCC (3.4.4) はオプション ' " でそれを受け入れます。理想的には、関数宣言には完全なプロトタイプを含める必要があります。pqr()
int
int
-std=c99 -pedantic
pqr()
は省略記号で定義されていましたが、そのプロトタイプは理論上必要です!)