トップページ

本棚


両手で1000まで数えられますか?:2進法の話
数値 - 危険物取り扱い注意
100 × 200 =32?:変数のオーバーフローの話
パリティビット
小数の扱いについて
ぽいんた
ぽいんた2
ぽいんた3
ジ・オリジン
ジ・オリジン:補足
かっこつける話
かっこつける話2
文字列のこと
タイミングの話
拡張性の話
取り込む話
staticな話

コンパイルの話1
コンパイルの話2:止まらぬビルド
コンパイルの話3:マシン語に落ちるということ1:メモリの話
コンパイルの話4:マシン語に落ちるということ2:最適化
コンパイルの話5:マシン語に落ちるということ3:変数とスタック
コンパイルの話6:コンパイラはそもそも何をやってくれるのか??
リンクの話
プリプロセッサの話

OS、というもの

オブジェクト指向1
オブジェクト指向:2
オブジェクト指向:3

オブジェクト指向:番外 C言語のソースファイルの話
オブジェクト指向:番外 C言語での「再利用性」と「カプセル化」データ構造とアルゴリズム


抽象的な話

寝込んで布団の中で考えたこと
こんなの、常識??
お仕事プログラミング
ソフトでハードなプログラム
プログラムするということ
お勉強
プログラムを学ぶということの補足
C言語:「学問」と「実務」
統合開発環境
C言語ってポータブルですか?
C言語ってポータブルですか?:2
あなたは、どう読みますか?
ああ勘違い
試してガッテン
低級品
質問をするということ
ポカ
「何もしない」 != 「無駄」
エディタの話
もっと手を抜こう

いまどきの、アセンブラ

VisualStudio2005
VisualStudio2005:2

戦争の防ぎ方、に対する私の考え
身近な差別
改革
地球に優しいなんて大嘘
統計で嘘をつく方法

言葉について
言葉について:2

神が死んだということ
善悪の彼岸から、力への意思を目覚めさせるということ

本を読むということ
本を読むということ:2

絵を描く話
地図
地球儀

オカルトのお話
がんだむさん
RPGソフトウェア
記紀神話の不思議



メニュー

※上記の広告は60日以上更新のないWIKIに表示されています。更新することで広告が下部へ移動します。

C言語などのプログラミングにおいては、「コンパイル」という作業をすることで実行可能なバイナリを生成します。

これをしないと、いくらすばらしいコードを書いたとしても、それは単なるテキストファイルでしかありません。

では、このコンパイルを行ってくれる「コンパイラ」って、正味な話何をやってくれてるんでしょうか??


われわれプログラマがコンパイラに期待していることは、
①何よりもまず実行可能なバイナリを吐くこと
②できたら「最適化」を行ってより効率のいい処理に置き換えてくれること
でしょう。

②については、以前にも書いてあるのでここでは割愛。

①について、テキストファイルを読み込んで、それを実行可能なバイナリに変換するには、いったいどういう手順が行われているのかを、ここでは書きたいと思います。


プログラマから「コンパイルしてよ!」と指示を受けたコンパイラがまず最初にやること。それはソースファイルの読み込みですね。至極当たり前のことですが。

ソースファイルを読み込んだ後、'#'で始まるプリプロセッサ命令を処理します。
この時にインクルードファイルを展開するので、これ以降の処理にとってはヘッダファイルに宣言された共通の関数も当該ソースファイル内でローカルに宣言された関数も、見え方は同じになるというわけです。また、#defineされた定数やマクロもこの時点で展開されます。



この処理の次に、【字句解析】と呼ばれる処理を行います。

言葉だけ聞くとなんだか小難しいわけですが、何のことは無く上で展開した後のソースを最初から1文字ずつ読み込んで処理していくだけです。

具体的には
①空白は読み飛ばす
②一定のルール(空白や確固で区切るなど)に従ってトークンとして切り出す。
③切り出したトークンがアルファベットで始まりアルファベットまたは数字で構成されていれば、それが予約語か識別子かを判別
④数字のみのトークンは数値と判定する
⑤演算子のトークンは演算子と判定する
といった処理を行います。

if(A == (B+C))
という文があったとすれば、
まず
[if] [(] [A] [==] [(] [B] [+] [C] [)] [)]
というトークンに分解されます。

そしてそれぞれのトークンに、
[if]→ 予約語
[(] → 括弧(区切り文字)
[A] → 識別子
[==]→ 演算子
[(] → 括弧(区切り文字)
[B] → 識別子
[+] → 演算子
[C] → 識別子
[)] → 括弧(区切り文字)
[)] → 括弧(区切り文字)
などといった区分を付加します。

C言語で実装するなら区分を列挙型で定義して構造体に区分と実際のトークンへのポインタをもつような感じでしょうか?



そして次に、切り出したトークンを用いて【構文解析】を行います。

これも言葉は小難しいですが、要は一定のルールに従ってトークンとトークンの並びから構文ツリーを作成していく処理のことです。

この処理は言語に依存します。演算子の優先順位や、そもそも言語によって演算子自体会ったりなかったりなんてこともあるわけで。

上の例の場合だと、
 if
 \
 == 
 /\
 A +
  /\
 B C
こんな感じになるのかな?

ここの処理の実装方法を書いていくと長くなるので、それについてはその気になったときに書きます。



つづいてさらに【意味解析】を行います。

上の例だと、すべては書きませんがたとえば
○「識別子B」と「識別子C」がぶら下がっているのは「演算子+」であるので、BとCの加算をおこなう必要がある
○全体が「予約語if」にぶら下がっているのでそれ以下がTRUEかFALSEで処理を分岐する必要がある
などということを判断するわけです。



そして最後にその判断を元に、それを実現するマシン語あるいは中間コードなどを吐くわけです。


実際の商用コンパイラなどは、最適化処理などもっともっと複雑なことをやっているわけですが、大まかな流れとしてはこんな感じです。
いつもがんばってくれているコンパイラさんが、どんな働きをしているのか。それを知ることは無駄にはならないでしょう(多分)。




| 新しいページ | 編集 | 差分 | 編集履歴 | ページ名変更 | アップロード | 検索 | ページ一覧 | タグ | RSS | ご利用ガイド | 管理者に問合せ |
@wiki - 無料レンタルウィキサービス | プライバシーポリシー