2017-07-30 3 views
1
//File a.c 
void main() 
{ 
    test(); 
} 

//File b.c 
#include<stdio.h> 
void test() 
{ 
    printf("Hi, I am test."); 
} 

このコードは "gcc a.c b.c"を使用してコンパイルします。それから私は 'a.out'を実行し、出力は「こんにちは私はテストです。」私の質問はa.cファイルにtest()の宣言がないので、なぜコードがコンパイルされるのですか? Cで宣言のない別のファイルで関数を呼び出すと、コンパイルエラーは発生しません。

+0

これらは接続されていますか? –

+1

警告が表示されましたか?あなたのコードに 'gcc'を使用すると、' 'test''の暗黙の宣言の警告が表示されます。 – lurker

+0

Cチュートリアルの本を購入してください。それから、なぜあなたは理解するでしょう。警告をオフにしないでください –

答えて

2

機能は、リンカーは、プログラマによって書かれた何#includeexternがない場合でも、bをファイルへのファイルaから機能を接続することができるだろうという意味、デフォルトでexternです。

私のgccはこの警告でそれをコンパイルしました:warning: implicit declaration of function...意味、見ることによってtest();コンパイラは何を推測してtestであり続けます。私はあなたが注意すべきだと思うstaticカウンターデフォルトextern

ことの一つは、このimplicit declarationもコンパイラ推測testの戻り値の型を作るされ、そしてそれは考えるであろうから、失敗しただろうことstaticとしてtestを定義していた場合タイプはintです。それは問題を引き起こす可能性があります。

1

これはC標準(少なくとも1999年以前)で必要とされているため、コードがコンパイルされます。 1999年の標準ではサポートが中止されましたが、これ以降も多くのコンパイラがサポートしていますが、そのような場合に警告するように設定することもできます(暗黙の宣言など)。

具体的には、C89/90と事前標準Cとの下位互換性の理由から、関数を呼び出すコードによる暗黙的な呼び出しでは、関数はintを暗黙的に宣言し、可変引数リストを受け入れます。関数が同じ名前を持っているので

これは、コンパイラがa.c

リンクを通じて働いているときに起こることですが、それは、動作します。

実際には、関数の呼び出し方法(戻り値の使用方法と引数の種類数)が関数の定義方法と一致する場合に機能します。一致するものがない場合、結果は未定義の可能性があります。たとえば、関数が4つの引数で定義され、すべて4を使用するが、呼び出し元が3を提供する場合、その動作は未定義です。同様に、関数がdoubleを返すように定義されていても、呼び出し元はintを返すと仮定しています。

実際には、すべてのコンパイル単位が呼び出される前に(たとえば、ヘッダーを含めて)、すべてのコンパイル単位ですべての関数を宣言する方がよいです。これにより、コンパイラは、関数の呼び出し方法が宣言と一致するかどうかをチェックできます。

すべてのC標準でmain()voidではなくintを返します。 voidを返すmain()のサポートは、コンパイラ拡張です。

関連する問題