4

test.c、foo.c、foo.h の 3 つのファイルがあります。
foo.ci で

#include "foo.h"

test.ci で

#include "foo.c."  

次に、コードをコンパイルするときに gcc -o test test.c を使用すると、コンパイルされます。

しかし、私の教授は私に言った、私は使うべきです

#include "foo.h" 

ではなく私のtest.cの中にあり、#include foo.cこのようにコンパイルする必要があります

gcc -o test test.c foo.c

2番目の方法がより好ましいですか?もしそうなら、なぜですか?これら2つのコンパイルの違いは何ですか?

4

7 に答える 7

7

ほとんどの場合、ソースファイルを含めないでください(別のスクリプトによって動的に生成されたコードを含めたい場合を除きます)。ソースファイルはコンパイラに直接渡されます。ヘッダーファイルのみを含める必要があります。

あなたの教授が提案する方法は正しいですが、この場合、次の方法の方が教育的価値があります。

gcc -c test.c
gcc -c foo.c
gcc -o test foo.o test.o

最初の2行は、各ソースファイルをオブジェクトファイルにコンパイルします。3行目は、実際にはコンパイルせず、リンカーを呼び出して2つのオブジェクトファイルから実行可能ファイルを生成するだけです。アイデアは、コンパイルリンクを区別することです。これは、教授が提案する方法で透過的に実行されます。

于 2013-02-28T15:52:40.810 に答える
2

.c ファイルを他の .c ファイルに含めない主理由は次のとおりです。#include

  • 定義エラーの重複を避ける:foo.cが function を定義していると仮定しますfoo()。を使用する他の 2 つのファイルがあるためfoo()#include "foo.c"両方に含まれています。プロジェクトをビルドしようとすると、コンパイラはfoo.c複数回変換します。つまり、foo関数を定義しようとする試みが複数回発生し、診断が発行されて停止します。

  • ビルド時間を最小限に抑える: 重複定義エラーを導入しなくても、同じコードを不必要に再コンパイルすることになります。で、1 行の変更を行う必要があること#include "foo.c"に気付いたとします。再構築すると、不必要に の内容を再翻訳することになります。 bar.cbar.cfoo.c

C では、ソース ファイルを個別にコンパイルし、結果のオブジェクト ファイルをリンクして、アプリケーションまたはライブラリを構築できます。理想的には、ヘッダー ファイルには、非定義オブジェクト宣言、関数プロトタイプ宣言、型定義、およびマクロ定義のみを含める必要があります。

于 2013-02-28T17:05:57.503 に答える
1

#includeソースファイルの代わりにヘッダーファイルを作成し、ソースファイルを個別にコンパイルするのが一般的な方法です。関心の分離により、大規模なプロジェクトでの作業が容易になります。あなたの例では、それは些細なことかもしれませんが、何百ものファイルを処理する場合は混乱する可能性があります。

教授が提案する方法でそれを行うことは、各ソースを別々にコンパイルできることを意味します。したがって、ソースが数千行のコードである大規模なプロジェクトがあり、で何かを変更した場合は、一緒に再コンパイルする代わりに、test.c再コンパイルするだけで済みます。test.cfoo.c

これが理にかなっていることを願っています:)

于 2013-02-28T15:53:01.530 に答える
1
gcc f1.c f2.c ... fn.c -o output_file
于 2013-03-14T01:13:34.357 に答える
1

gcc で複数のファイルをコンパイルする場合は、次を使用します。

gcc f1.c f2.c ... fn.c -o output_file
于 2013-02-28T15:53:16.193 に答える
1

.c ファイルを含めることはお勧めできません。

あなたの場合、 test.c と foo.c の両方に foo.h を含めますが、これをヘッダーファイル内に追加します

#ifndef foo.h 
#define foo.h

..your header code here


#endif

上記の方法でヘッダーを作成すると、念のため、ヘッダーを複数回含めることができます。

コードをファイルに入れる方法について>

foo.h で

すべてのグローバル構造と変数を、使用する関数プロトタイプとともに配置します。

foo.c で

ここでモジュラー関数を定義します

test.c で

ここには一般的に main() があり、foo.c で定義された関数を呼び出してテストします。

通常、すべてのファイルを同じフォルダーに配置すると、コンパイラーがそれらを見つけて個別にコンパイルし、後でリンカーによって接続されます。

于 2013-02-28T16:02:11.073 に答える
1

短い答え:
はい、2 番目の方法がより好ましいです。

長い答え:
この特定のケースでは、同じ結果が得られます。
ディッパーを理解するには、まず「#include」ステートメントが基本的にインクルードされているファイルをコピーし、「#include」ステートメントの代わりにその値を入れることを知っておく必要があります。
したがって、「h」ファイルは、いくつかの異なるファイルが含まれても問題ない前方宣言に使用されます。
「c」ファイルには実装がありますが、その場合、両方のファイルが同じ関数を実装すると、それらをリンクする際にエラーが発生します。
「test2.c」があり、foo.c も含めて、それを test.c とリンクしようとすると、foo.c の 2 つの実装ができます。しかし、3 つのファイルすべて (foo.c、test.c、および test2.c) に foo.h のみを含める場合でも、それらをリンクして foo を引き起こすことができます。

于 2013-02-28T15:57:26.600 に答える