2017-08-29 22 views
1

#includeはプログラムの先頭とメイン関数の外側に記述する必要がありますか?Cプログラムのどこにでもプリプロセッサディレクティブを書くことができますか?

私は、メイン関数内の#defineプリプロセッサを使用してみました、それは私が定義するディレクティブが唯一例えば がprintf("%d",PI); #define PI 3.14がすると言うの#define行の後に使用することができます使用して定義されている唯一のexception..thatが一定であるとうまく働いエラー "Undefined symbol PI"を返します。しかし、次のコードでは、私はすべてのエラー

#define PI 3.14 
printf("%d",PI); 

に遭遇しなかったCは、手続き型言語と手続き型言語はアプローチをトップダウン実装されているため、これはありますか?

また、main関数や他のプリプロセッサディレクティブで#defineしか使用できないことを知りたいですか?もし私たちがそれを使うことができたら? それ以外の方法で、#includeの代わりにmain関数内のすべてのプリプロセッサディレクティブを使用できますか?

+0

」すべてのコンパイル警告を有効にする – chux

+1

C標準(と私はPOSIX標準と信じている)には、次のことが必要であることに注意してください。それらが定義するヘッダはファイルスコープに含まれなければならず、外部宣言のスコープ内に含まれていなければなりません(関数宣言や変数宣言の途中で)。ヘッダーにシステムヘッダが含まれている場合は、後でファイルスコープの規則に従わなければなりません。インクルードは通常ファイルの先頭にありますが、これは必須条件ではありません。 –

答えて

2

プリプロセッサディレクティブを配置できない唯一の場所はマクロ展開です。唯一の例外は#pragmaです。_Pragma()と書くこともできます。

これは「手続き型」とは関係ありませんが、Cは8つの翻訳フェーズで定義されているため、それぞれが次の段階の前に完全に完成したままです。詳細については、C11標準の5.1.1.2項を参照してください。それは便利は、ファイルの開始後のプリプロセッサディレクティブを使用するときの


一例がためである"X Macro" technique(多くの人々は唯一の「これらの.defファイル」として知っています)。

1

プリプロセッサディレクティブはほとんどどこでも動作します。もちろん、コードを混乱させるとコードがかなり混乱することがあります。

+0

残念ながら、#includeはどこでも動作していません。なぜそうですか?私は単純な例を取った。int main(空白){#include }と言って、ターボCコンパイラではほとんどが未定義のシンボルである6エラーを受け取った。 –

+3

'#include 'は本当にどこでも動作する...しかし、インクルードされたファイルの内容を '#include'ディレクティブを置いた場所に貼り付けます。したがって、 'main'の中に置くと' math.h 'の内容を 'main'関数の中に置くことになります。おそらくコンパイルされません。しかし、 'main'関数の中でコンパイルするコードを含むファイルを' #include 'した場合、それはうまく動作します(実際にはそうするのはお勧めできません)。 –

+0

@CharlesSrstka、#includeは多くの場所で動作します。グローバルなスコープに含めるように書かれたヘッダーです。 '#define some_macro some value'と#include" special.c "を持つソフトウェアがあります。配列はインクルードされたファイルで埋められることがあります。 – osgx

1

プリプロセッサは、コンパイラがオブジェクトコードへのソースコード変換を実行する前に、その作業を行います。前処理は主に文字列の置換処理であるため、コード内のどこにでも置くことができます。もちろん、結果として生じる拡張が構文的に正しくない場合、展開されたソースコードはコンパイルに失敗します。

一般的に許容されるプラクティスは、コンパイルディレクティブを関数内に埋め込んで、関数がプラットフォーム固有のAPIを使用できるようにすることです。その性質上

void some_wrapper_function() { 
#if defined(UNIX) 
    some_unix_specific_function(); 
#elif defined(WIN32) 
    some_win32_specific_function(); 
#else 
    #error "Compiled on an unsupported platform" 
#endif 
} 

、ディレクティブ自体は、通常、行の先頭に定義する必要があり、ないどこかにソースラインの真ん中インチしかし、定義されたマクロはもちろんソースのどこにでも現れることができ、あなたのディレクティブで定義された置換規則に従って置き換えられます。

+1

'_Pragma'はプリプロセッサ演算子であり、ディレクティブではありません。演算子のバージョンはマクロを使用できる場所であればどこでも使用できますが、' #pragma'のように動作します。 – jxh

+0

注:https://stackoverflow.com/documentation/c/1337/compilation/28469/the-translation-phases – jxh

0

ここでは、#ディレクティブは伝統的にプリプロセッサによって解釈され、コンパイル前に実行されることを理解することです。プリプロセッサは新しいソースファイルを生成し、コンパイルされます。現代のコンパイラはデフォルトではそのようには動作しませんが、同じ原則が適用されます。

は、だから、あなたは、この行から始まる私のソースコードにfoo.hというの全体の内容を挿入」言っている

#include "foo.h" 

を言うとき。私は以下のコードを「ソースの開始時以外の場所にそれを使用するあなたは、ソースファイルにほとんどどこでも、このディレクティブを使用することができますが、それはほとんど役に立ちません(多くの場合、読めない)です。

関連する問題