2012-10-19 8 views
5

typedefとdefineの違いを理解しようとしています。良いポストの多くは、しかし、私は前処理がコンパイラで正確に意味するもの

#defineは、プリプロセッサトークンで述べポストを理解できない、特別this previous question on SOでありますコンパイラ自身がそれを見ることはありません。
typedefはコンパイラトークンです。プリプロセッサはそれを気にしません。

もう少し詳しく説明してください。私はここでプリプロセッサという用語と混同しています。

答えて

5

プリプロセッサは、の前にコンパイラを実行し、基本的にテキスト置換を実行するプログラムです。あなたが書くとき:

#define X 10 

int main() 
{ 
    int x = X; 
} 

を前プロセッサは、入力として、そのファイルを取る、それはことだ、と出力ん:

int main() 
{ 
    int x = 10; 
} 

そして、コンパイラは、前処理された出力とのことを行います。一方、コンパイラが理解できる構造体である。

あなたが書くとき:

typedef unsigned int uint_32; 

コンパイラはuint32が実際にunsigned intの別名であることを知っています。このエイリアスはコンパイラ自体によって処理され、単純なテキスト置換よりも少し論理があります。これは単純な例で明らかになった:

typedef int my_int; 

int main() 
{ 
    unsigned my_int x; // oops, error 
} 

typedefがうまくいく単純なテキスト置換メカニズム(プリプロセッサがあるように)、その後だったが、それが許可されていないとコンパイルに失敗します。

5

プリプロセッサは、コンパイルが開始される前に発生するフェーズです。それは特定のマクロとシンボルを読み込んで置換する。通常は1〜2回通過します。ソースファイル全体をスキャンし、マクロを置換または展開するシンボルテーブルを生成します。

すべての置換が完了した後、シンタックスアナライザは、ソースファイルのレキシング解析、抽象構文木の生成、コードの生成、ライブラリのリンク、実行可能ファイル/バイナリの生成を引き継ぎます。

C/C++/ObjCプリプロセッサのDIRECTIVESは、「define」、「ifdef」、「ifndef」、「elif」、「if」、「endif」などのディレクティブ名の後に「#」を付けて開始します。

前処理、BEFORE

:前処理AFTER

#define TEXT_MACRO(x) L##x 
#define RETURN return(0) 
int main(int argc, char *argv[]) 
{ 
    static wchar_t buffer[] = TEXT_MACRO("HELLO WORLD"); 
    RETURN ; 
} 

int main(int argc, char *argv[]) 
{ 
    static wchar_t buffer[] = L"HELLO WORLD"; 
    return (0); 
} 

私の記憶が正しければ、カーニハンとリッチーの著書 "プログラミング言語C" 第2版は、彼らが示す例を、持っていますホ自分のプリプロセッサを作成し、それがどのように機能するかを示します。また、Plan9 Cコンパイラは2つのプロセス(コンパイルと前処理)を分離しました。独自のプリプロセッサを使用できるようにします。

An interesting preprocessor for multiple languagesWrite your own pre-processorを確認してください。これらのプログラムの入力と出力を見ると、プリプロセッサの実際の内容をより深く理解することができます。

別の小さな秘密:あなたは、プリプロセッサを持っている場合は、スペイン語/ラテン語/ドイツ語Cをコーディングすることができます:)

+0

ありがとうございました – Murphy316

+0

+1正解です。あなたが最初にそれを与えました。しかし、良い例があります。 – Alex

+0

よくあるご質問には、 – Murphy316

2

を、それは、コンパイルに来るとき、あなたのソースコードは、ステップの多くを通過します。これらのステップでは、事前処理が行われます。

プリプロセッサは、コンパイラの前に実行されるプログラムであり、すべての##include#define、などのように、指示を開始し実行。..あなたの特定のケースで

#define WORD newwordは言うディレクティブです:「すべての発生を置き換えますプログラムのコンパイルを試みる前に、新しい単語でWORDの "

実際に動作させたい場合は、cpp file.cを実行し、出力内容を調べてその動作を理解してください。

ファイル。cppの後になるだろうC

#define WORD "newword" 

int main() 
{ 
    printf("this is word: %s\n", WORD); 
    return 0;       
} 

は、他の一方で、それが使用されている "私はおよそTypeを話せば、私はstruct more_complex_typeが意味することを理解して" と言うために使用され、

int main() 
{ 
    printf("this is word: %s\n", "newword"); 
    return 0; 
} 

のtypedefを実行しますコンパイル時には、cppの前後で同じままになります。

2

プリプロセッサは、コンパイラがコードをコンパイルする前に実行される「エンジン」です。 #define #includeはプリプロセッサディレクティブまたはマクロであるため、プリプロセッサエンジンはディレクティブに関連するコードを実行します。プリプロセッサが完了すると、コンパイラはディレクティブ/マクロのどれも見ることができません。 しかし、typedef,if,whileなどのような構造体は、コンパイラによって理解されています。

+0

ビジュアルスタジオでは、コードを書くときに入力中にプリプロセッサを実行します(つまり、プリプロセッサを宣言して使用しようとした後)か? – Murphy316

+0

すれば意味があります。さもなければ、インテリセンスは役に立たないでしょう。 –

3

CおよびC++プリプロセッサは、非常に早い時期に発生するコンパイルの論理フェーズです。プリプロセッサは、ファイルの条件付き除去部分によって、#includeによって指定されたヘッダファイルのテキストを含めることによって、翻訳単位にソースファイルを変換する(#if#elif#else#endif、及び#ifdef#ifndef変異体)マクロを実行して、及び置換。マクロは#defineで定義されています。ソースを走査するプリプロセッサによってマクロを検出することができる。

プリプロセッサは#で始まるほとんどの行を削除(それだけ#lineディレクティブの後ろに残し、ソースはどこから来たのか#lineに独自の省略形の変異体は、背後にコンパイラに指示します)。コンパイラ本体は、前処理の結果を見て、定義されているソースコードをコンパイルします。

プリプロセッサは通常、typedefという語を変更しません。非常識なプログラマがtypedefのマクロを定義でき、プリプロセッサは気にしないかもしれません。プログラマーは正当にシステムヘッダーを含めることができませんでしたが、言語内のキーワードと同じ名前で定義されたマクロがあります。そうでなければ、typedefはコンパイラにとって問題であり、プリプロセッサには問題がありません。だから、sizeof()です。プリプロセッサが理解できるものではありません。

通常、前処理された出力を表示するためのコンパイラオプションがあります。 gccの場合、オプションは-E-Pです。

1

これは、プリプロセッサがコンパイラの前で実行され、コンパイラに渡す前にソースコードを変更することを意味します。したがって、コンパイラはコードの一部を見ることはありません。例:あなたはこれをコンパイルすると

#define ONE 1 
int x = ONE; 

、プリプロセッサはこの中にそれを変更します。

int x = 1; 

とコンパイラにその新しいテキストを渡します。したがって、コンパイラは、テキストONEを表示しません。

関連する問題