例えば:
file1.c
もっている:
static const struct
{
int a;
int b;
int c;
} mystruct = { 1, 2, 3};
file2.c
もっている:
#include <stdio.h>
#include "file1.c"
等々。
これは大丈夫ですか?
これは大丈夫ですか?私にお知らせください。ありがとう。
これは技術的には機能しますが、お勧めしません。代わりに、宣言をヘッダー ファイルに入れ、両方の .c ファイルを project/makefile/etc に含めることをお勧めします。
これはより「標準的な」作業手段になり、プロジェクトをより保守しやすくします。
はい、良い動機があれば問題ありません。たとえば、ソース コードの重複を回避するのに役立つ場合があります (バイナリ レベルで重複が発生する場合でも)。または、マシンで生成されたコードの一部 (別のコンパイラによって生成されたパーサーなど) を操作できる場合があります。 )。一部のプラットフォームでは、パフォーマンスやフットプリントの改善が得られる場合もあります。これは、コンパイラが、別の変換単位でfile1.c
ある場合には不可能な、より最適化された命令 (たとえば、コードが含まれている場合の相対的なローカル呼び出し) を選択できるためです。file1.c
動機が十分でない場合は、いくつかの分野で問題が発生する可能性があるため、避ける必要があります。頭に浮かぶいくつかは次のとおりです。
file1.c
file1.c
file1.c
定義したすべてのシンボルが内部リンケージを持たない場合、リンク エラーが発生する可能性があります。実際のコードまたはデータ定義 (単なる宣言とは異なる) を含むファイルを #include すると便利な場合もありますが、設計されていない限り、.c 拡張子の付いたファイルに名前を付けるのは好きではありません。直接コンパイルします。私は通常、#include されるように設計されているが、複数の宣言を含むファイルには、拡張子 ".i" を付けて名前を付けます。たとえば、私が使用している組み込みプロセッサでは、静的構造の要素にアクセスするコードは、構造ポインタを指定して要素にアクセスするコードの約 4 分の 1 のサイズであり、約 4 倍の速度で実行されます。したがって、構造上で動作する実質的なコード ブロックが存在する場合、コードは合理的に迅速に実行する必要があり、コードが動作しなければならない構造が 2 つあります。
このイディオムを実装するための私の好みの方法は、次のようなことです。
#THINGIE 0 の定義 #THINGIE_STRUCT を定義する thingie0 #include "thingie.i" #undef THINGIE_STRUCT #undef THINGIE #THINGIE 1 の定義 #THINGIE_STRUCT を定義する thingie1 #include "thingie.i" #undef THINGIE_STRUCT #undef THINGIE
少し醜いですが、間接的な構造体へのアクセスが非常に苦手なマシンでは価値がある場合があります。
これは避けてください。プロジェクトの他の部分に役立つ/必要なタイプ定義と関数シグネチャをfile1.cから、プロジェクトの他の部分に含めることができる共通のヘッダーファイルにプルします。
通常、file1.cをfile2.cに含めると機能します。これは、ファイルを含めるだけで、を別のファイルのコンテンツに置き換えるため#include
ですが、プロジェクトの複雑さが増すにつれて壊れ始め、複数定義されたシンボルで問題が発生し始めます。 。
あなたはここであなたの質問に対する良い答えを見つけることができます:
私自身、それをヘッダーファイルfile1.hとして保存し、それをインクルードします。
いいえ、常に ac ファイルを含めることは避けてください。
ヘッダー ファイルには、定義/プロトタイプのみを含める必要があります。
c ファイルには関数が含まれているため、含めないでください。
技術的には、これは単なるファイルの名前であり、.c拡張子はファイルの内容には影響しません。必要に応じて.zと呼ぶこともできます。あなたの質問に答えるには:はい、できます。しかし、これは慣習に反しており、ヘッダー ファイル内にある必要があります。
ここでは基本的に技術的な考慮事項はありません。つまり、この決定は、ソフトウェアまたはハードウェアの動作方法とは本質的に関係ありません。
この決定における考慮事項は、人的考慮事項です。ソース コードの編成方法について決定を下し、規則を作成するときは、次のような目標を達成するために行います。 コードをより簡単に記述できるようにする。コードの保守を容易にする。ミスを減らす。
これらは人間の考慮事項です。人間は、完全な機械とは異なる特定の方法で行動します。彼らは間違いを犯します。彼らは物事を忘れます。それらは、扱いやすいサイズに分割された問題でうまく機能します。
一般に、ヘッダー ファイルは、複数のソース ファイル (多くの異なるプログラムで多くの異なる人々によって使用されるライブラリ ルーチンなど) で使用されるものを宣言し、宣言を定義から分離するために使用されます。ソース ファイルにこれらのルーチンの定義を含める必要なくルーチンを使用します。技術的には、宣言を各ソース ファイルにコピーすると、コンパイラから同じ結果が得られます。しかし、これはいくつかの目標に違反しています。ルーチン定義に変更があるたびに、宣言のすべてのコピーを変更する必要があるため、コードを書くのが難しくなります。また、エラーが増加します。変更が必要なコピーの 1 つを忘れたり、見落としたりすることがあります。
したがって、構造体オブジェクトの定義を .c ファイルに入れることができます。ヘッダーファイルに入れることもできます。これはあなたの目標を達成するのに役立ちますか?
構造体オブジェクトは static として宣言されていることに注意してください。複数のソース ファイルでコンパイルされた場合、生成される各オブジェクト ファイルには個別のコピーが作成されます。オブジェクト ファイルを 1 つの実行可能ファイルにリンクすると、同じデータの複数のコピーが作成されます (使用する開発ツールが非常に優れている場合を除きます)。それはもったいないので、得策ではありません。ただし、1 つのソース ファイルのみでコンパイルする場合は、人間の考慮事項のみが問題になります。誤って file1.c と file2.c の両方をコンパイルする可能性はありますか? 他の人がこのコードに取り組むとき、mystruct がどのように、そしてなぜ定義されているかを理解してくれるでしょうか? 等々。
私は、別々のソース ファイルでオブジェクトを定義することが適切なプロジェクトに取り組んできました。たとえば、計算されたデータのテーブルを準備し、それをプログラムのソースに含める必要がある場合があります。このような場合、そのテーブルを別のソース ファイルに保持することは合理的です。
通常、このような場合に使用される解決策は、テーブルの定義のみを含むソース ファイルを使用することです。そのソース ファイルでは、「extern」キーワードを使用して、テーブルが外部として宣言されます。ヘッダー ファイルでは、テーブルは宣言されますが、定義されません。テーブルを使用する各ソース ファイルには、テーブルを宣言するヘッダー ファイルが含まれます。テーブルを定義するソース ファイルには、ヘッダー ファイルも含まれます。(そうすると、ヘッダーファイルとソースファイルに不一致があると、コンパイラーがエラーを出します。これにより、ヘッダーファイルのミスを回避できます。)
テーブルを定義するソース ファイルは、オブジェクト モジュールにコンパイルされます。プログラムの他のものを含むソース ファイルは、個別のオブジェクト モジュールにコンパイルされます。次に、リンカーを使用して、すべてのオブジェクト モジュールを 1 つのプログラムに結合します。
あなたの場合、オブジェクトを静的であると宣言する理由はありますか? 存在する場合は、その定義を別のソース ファイルに含めるというこのソリューションが適切な場合があります。しかし、そのような理由があることはまれです。定義を別のファイルに入れることがソースの編成に役立つと思われる場合は、上記のようにオブジェクトを外部として宣言し、ソースを別々にコンパイルすることが適切な解決策である可能性が高くなります。
GCC を使用する場合、次のようにソースをオブジェクト モジュールにコンパイルできます。
gcc -c -o name0.o name0.c gcc -c -o name1.o name1.c
「-c」スイッチは、「実行可能ファイルを作成するためのリンクの次のステップを実行する代わりに、オブジェクトにコンパイルして停止する」ことを示します。「-o」スイッチは、出力ファイルの名前を指定します。
次に、オブジェクト モジュールを次のように実行可能ファイルにリンクできます。
gcc -o プログラム名0.o 名前1.o