3

私はそれを示すためにこの小さなコードを持っています:

#include "stdio.h"

int main() {
    int a = testfunc();  // declared later
    printf("%d", a);
    return 0;
}

int testfunc() {
    return 1;
}

エラーなしでコンパイル1され、期待どおりに出力されます。

実際に見る: http://ideone.com/WRF94E

なぜエラーが出ないのですか?それはCの仕様の一部ですか、それともコンパイラ関連のものですか?

4

6 に答える 6

5

関数testfunc()は暗黙的に宣言されています。コンパイラは署名チェックを実行できないため、正しく呼び出さなかった場合にランタイムエラーが発生する可能性があります。

これはC仕様の一部です。ただし、C仕様での推奨事項は、現在のファイルの先頭またはヘッダーファイルで、実装および使用する予定のすべての関数を宣言することです。

于 2012-11-28T10:11:38.010 に答える
2

なぜなら、デフォルトでは、コンパイラは宣言されていない関数を次のように見なすからです。

int function_name ();

内部的には、宣言されていない関数はreturn型をintと見なし、任意の数の引数を受け入れます。実際の関数とも一致します。だから問題ありません。

于 2012-11-28T10:11:29.977 に答える
1

コンパイラーは、それを呼び出すために関数定義を確認する必要はありません。引数をチェックするためのプロトタイプのみが必要です。引数がない場合、コンパイラーは関数が返さintれ、実行していることを知っていると想定します。ただし、リンカがシンボルのみを解決できない場合にリンクすると、エラーが発生します。

于 2012-11-28T10:20:22.667 に答える
1

これはコンパイラに依存します。一部のコンパイラはエラーを発行し、他のコンパイラは警告を発行しますが、他のコンパイラは何も発行しません。コンパイラの義務は、正しい引数で関数を使用していることを確認することだけです。宣言しない場合、コンパイラは関数の誤用をチェックして警告することはできませんが、関数を呼び出すためのコードを生成することはできます。一方、リンカの役割は、関数が実装されていることを確認し、コンパイラによって以前に生成された呼び出しにそのアドレスを配置することです。関数が実装されているため、リンカーは正常に機能します。

コンパイラはあなたをチェックしないので、引数を使って関数を呼び出してみることができます。呼び出しは機能する可能性がありますが、プログラムがクラッシュする可能性もあります。

于 2012-11-28T10:13:35.890 に答える
1
int a = testfunc();

int testfunc() {
    return 1;
}

C ではデフォルトの関数シグネチャが同じであるため、エラーは発生しません。

コンパイラに教えてもらいたい場合は、以下のデモを参照してください。

前方宣言なしでこのように呼び出すと、コンパイラーがエラーを出すのがわかります。

int a=testfunc(5.4);

int testfunc(float f)
{
 return 1;
}

注 : C でのベスト プラクティスはforward declaration、プログラムで使用する関数を指定することです。

于 2012-11-28T10:19:41.237 に答える
1

ANSI C では、関数プロトタイプを宣言する必要はありません。ただし、それらを使用することをお勧めします。プロトタイプがなく、関数を呼び出す場合、コンパイラは、関数に渡すパラメーターからプロトタイプを推測します。コンパイラは、戻り値の型が int であると想定します。後で同じコンパイル単位で異なる戻り値の型で関数を宣言すると、コンパイル エラーが発生します。

于 2012-11-28T10:31:48.423 に答える