名前空間
変種
操作

翻訳フェーズ

提供: cppreference.com
< c‎ | language

C のソースファイルは、以下のフェーズを正確にこの順序で行ったかのように、コンパイラによって処理されます。 実際の処理系は、動作が同じである限り、複数のフェーズを合体させたり違う方法で処理したりしても構いません。

目次

[編集] フェーズ1

1) ソースコードファイル (一般的には何らかのマルチバイトエンコーディング (UTF-8 など) で書かれたテキストファイル) の個々のバイトがソース文字集合に処理系定義の方法でマップされます。 特に、 OS 依存の行末指示子が改行文字で置き換えられます。
ソース文字集合は、以下の96個の文字から構成される基本ソース文字集合をシングルバイトの部分集合として含む、マルチバイト文字集合です。
a) 5個のホワイトスペース文字 (スペース、水平タブ、垂直タブ、書式送り、改行)。
b) 10個の数字 ('0' から '9')。
c) 52個のアルファベット ('a' から 'z' および 'A' から 'Z')。
d) 29個の句読点文字 (_ { } [ ] # ( ) < > % : ; . ? * + - / ^ & | ~ ! = , \ " ')。
2) トライグラフシーケンスが対応する単一文字表現に置き換えられます。

[編集] フェーズ2

1) バックスラッシュが行末に現れた (直後に改行が続く) とき、バックスラッシュと改行の両方が削除され、2つの物理ソース行が1つの論理ソース行に結合されます。 これはシングルパスの操作です。 2個のバックスラッシュで終わる行に空行が続いても、3つの行は1つに結合されません。
2) このステップの後、空でないソースファイルが改行文字で終わっていない場合 (元々改行がなかったか、バックスラッシュで終わっていたかのいずれか)、動作は未定義です。

[編集] フェーズ3

1) ソースファイルがコメント、ホワイトスペース文字 (スペース、水平タブ、改行、垂直タブ、書式送り) の並び、および以下のプロプロセッシングトークンに分解されます。
a) <stdio.h>"myfile.h" などのヘッダ名。
b) 識別子
c) プリプロセッシング数値。 整数定数および浮動小数点定数に加えて、 1..E+3.foo0JBK などの一部の無効なトークンも含まれます。
e) +<<=<%## などの演算子および句読点。
f) その他のいかなるカテゴリにも収まらない個々の非ホワイトスペース文字。
2) それぞれのコメントが1個のスペース文字に置き換えられます。
3) 改行は維持されます。 改行でないホワイトスペースの並びが単一のスペース文字に折り畳まれるかどうかは未規定です。

入力が指定された文字までプリプロセッシングトークンにパースされた場合、次のプリプロセッシングトークンは、一般的には、たとえそれが後続の解析を失敗させるとしても、プリプロセッシングトークンを構成し得る最も長い文字の並びであるように取られます。 これは一般的に最長一致と呼ばれます。

int foo = 1;
int bar = 0xE+foo;   // エラー、無効なプリプロセッシング数値 0xE+foo。
int baz = 0xE + foo; // OK。
 
int quux = bar+++++baz; // エラー、 bar++ + ++baz ではなく bar++ ++ +baz です。

最長一致ルールの唯一の例外は以下の通りです。

  • ヘッダ名のプリプロセッシングトークンは #include 指令の中および #pragma 指令の中の処理系定義の位置でのみ形成されます。
#define MACRO_1 1
#define MACRO_2 2
#define MACRO_3 3
#define MACRO_EXPR (MACRO_1 <MACRO_2> MACRO_3) // OK、 <MACRO_2> はヘッダ名ではありません。

[編集] フェーズ4

1) プリプロセッサが実行されます。
2) #include 指令によって導入されたそれぞれのファイルに、フェーズ1から4が再帰的に適用されます。
3) このフェーズの終わりに、すべてのプリプロセッサ指令がソースから削除されます。

[編集] フェーズ5

1) 文字定数および文字列リテラル内のすべての文字およびエスケープシーケンスソース文字集合から実行文字集合に変換されます (実行文字集合は、少なくともフェーズ1に掲載されている基本ソース文字集合の96文字すべてが含まれている限り、 UTF-8 のようなマルチバイト文字集合でも構いません)。 エスケープシーケンスによって指定された文字が実行文字集合のメンバでない場合、結果は処理系定義ですが、ヌル (ワイド) 文字でないことは保証されます。

ノート: 処理系によっては、このステージで行われる変換はコマンドラインオプションによって制御できます。 gcc および clang はソース文字集合のエンコーディングを指定するために -finput-charset を使用し、エンコーディングプレフィクスを持たない (C11以上)文字列リテラルおよび文字定数内の実行文字集合のエンコーディングを指定するために -fexec-charset および -fwide-exec-charset を指定します。

[編集] フェーズ6

隣接する文字列リテラルが連結されます。

[編集] フェーズ7

コンパイルが行われます。 トークンが構文的および意味的に解析され、1個の翻訳単位として翻訳されます。

[編集] フェーズ8

リンクが行われます。 翻訳単位および外部参照を満たすために必要なライブラリ部品が、その実行環境 (OS) での実行のために必要な情報を含むプログラムイメージ内に収集されます。

[編集] 参考文献

  • C11 standard (ISO/IEC 9899:2011):
  • 5.1.1.2 Translation phases (p: 10-11)
  • 5.2.1 Character sets (p: 22-24)
  • 6.4 Lexical elements (p: 57-75)
  • C99 standard (ISO/IEC 9899:1999):
  • 5.1.1.2 Translation phases (p: 9-10)
  • 5.2.1 Character sets (p: 17-19)
  • 6.4 Lexical elements (p: 49-66)
  • C89/C90 standard (ISO/IEC 9899:1990):
  • 2.1.1.2 Translation phases
  • 2.2.1 Character sets
  • 3.1 Lexical elements

[編集] 関連項目

翻訳フェーズC++リファレンス