blog

ソフトウェア開発|コードのコンパイルについて知っておくべきこと

この便利なネズミ捕りの例えを使って、コンパイルされたコードを理解しましょう。...

Oct 13, 2025 · 5 min. read
シェア

この便利なネズミ捕りの例えを使って、コンパイルされたコードを理解してください。

プログラムを実行するにはソースコードをコンパイルする必要がありますが、オープンソースソフトウェアでは、誰もがソースコードにアクセスすることができます。自分でコードを書いてコンパイルして実行したい場合でも、誰かのプロジェクトをダウンロードして試したい場合でも、ソースコードが どのように扱われるのか、コンパイラがそのコードをどのように扱うのかを知っておくと便利です。

より良いネズミ捕りを作るために

ネズミ捕りをコンピュータに例えるのは普通ではありませんが、信じられないかもしれませんが、ネズミ捕りはあなたが使っている機器のCPUに似ています。古典的なネズミ捕りには、オンと解除という2つの状態があります。ネズミを捕まえるために仕掛けられた罠と、ネズミによって仕掛けられた罠と考えることができます。ある意味、ネズミ捕りはマウスを搭載したコンピュータのようなものです。このコードを想像して、架空の言語でプロセスを記述することができます:

  1. if mousetrap == 0 then
  2. There's a mouse!
  3. There's no mouse yet.

つまり、トラップの状態からネズミがいるかどうかを知ることができるのです。もちろん、ネズミ捕り器は絶対ではないので、ネズミが罠の隣にいる可能性もありますし、ネズミはまだ罠を作動させていないので、状態はまだYesのままです。ですから、この手順は改善することができます。

スイッチ

ネズミ捕りは一言で言えばスイッチです。スイッチを使えば、家の明かりをつけることができます。このスイッチから多くの情報が得られます。例えば、家の明かりの状態から、あなたが家にいるかいないかがわかります。

隣家の明かりの状態によって行動を変えることができます。隣家の電気が消えている場合は、大音量の音楽を止めてください。

CPUはこれと同じロジックを使いますが、数桁倍にしてミクロのレベルにまでスケールダウンしているだけです。CPUが特定のレジスタで電気信号を受信すると、他のレジスタをトリガーし、さらに別のレジスタをトリガーするという具合です。これらのレジスタが特定の意味を持っていれば、通信することができます。同じマザーボードのどこかのチップをアクティブにするとか、LEDを光らせるとか、画面のピクセルの色を変えるとか。

自分でまいた種は自分で刈り取るものです。もし本当に、ネズミ捕り器を1つしか持っていない代わりに、複数の場所でネズミを見つけたいのであれば、そのためのアプリを開発すべきです。ウェブカメラと基本的なイメージ認識ソフトを使えば、誰もいないキッチンをモデル化し、変化をスキャンすることができます。ネズミがキッチンに入ると、ネズミのいない元のイメージにピクセルの変化が生じます。このデータを記録し、ネズミを追跡して捕獲できるドローンがあれば、キッチンからネズミを追い出すことができます。その時点で、あなたは信号のオンとオフのマジックによって、より良いマウス・トラップを作成したことになります。

コンパイラ

コード・コンパイラーは、人間が読めるコードをCPUが理解できる機械語に変換します。これは非常に複雑なプロセスで、CPUが非常に複雑であることと、プロセスが厳密に「必要」である以上に柔軟であるためです。すべてのコンパイラが柔軟なわけではありません。コンパイラの中には、ただ一つの目標だけを念頭に置き、特定の形式のコードファイルだけを処理するものもあり、その結果、処理は単純明快になります。

幸いなことに、最近の汎用コンパイラーは単純ではありません。GNUコンパイラコレクションのgccコンパイラ --helpは50行以上のオプションを出力し、LLVMのclangコンパイラは1,000行以上の--helpを出力します。

コードをコンパイルする際には、たくさんのオプションがあります。

もちろん、ほとんどの人はすべてのオプションを知る必要はありません。GCCのマニュアルページは、Objective-C、Fortran、そして聞いたこともないチップアーキテクチャのためのものなので、わたしは読んだことがありません。しかし、異なるアーキテクチャ--64ビットでも32ビットでも--用にコードをコンパイルし、他の産業で遅れをとっているコンピュータ上でオープンソース・ソフトウェアを走らせることができるGCCの能力を、私は高く評価しています。

コンパイルのライフサイクル

また、コードをコンパイルするさまざまな段階を理解することも重要です。これはCプログラムの簡単なライフサイクルです:

  1. マクロ定義を含むCソース.cファイル、cppで前処理された.iファイル。
  2. マクロ定義が拡張されたCソース.iファイルは、gccによって.sファイルに変換されます。
  3. アセンブリ言語で書かれたテキストファイル.sファイルは、ターゲット.oファイルにコンパイルされます。
  4. CPU命令を含むバイナリオブジェクトコードと、他のオブジェクトファイルやライブラリ*.oファイルを、メモリ領域に依存しないオフセットで、ldを使用してリンクし、実行可能ファイルを生成します。
  5. 最終的なバイナリファイルには、必要なターゲットがすべて含まれているか、ダイナミックリンクライブラリ*.soファイルとしてロードされるように設定されています。

この簡単な例を試してみてください:

  1. $ cat << EOF >> hello.c
  2. #include
  3. int main(void)
  4. { printf("hello world ");
  5. return 0; }
  6. $ cpp hello.c > hello.i
  7. $ gcc -S hello.i
  8. $ as -o hello.o hello.s
  9. $ ld -static -o hello \
  10. -L/usr/lib64/gcc/x86_64-slackware-linux/5.5.0/ \
  11. /usr/lib64/crt1.o /usr/lib64/crti.o hello.o \
  12. /usr/lib64/crtn.o --start-group -lc -lgcc \
  13. -lgcc_eh --end-group
  14. $ ./hello
  15. hello world

利用可能な知識

コンピュータはとてもパワフルで使いやすくなりました。コンピュータはネズミ捕りや電気のスイッチほど単純ではありませんが、理解できないものでもありません。あなたはコードのコンパイルやリンクの方法、異なるアーキテクチャ向けのコンパイルについて学ぶことができます。それが分かれば、コードのデバッグもうまくできるようになります。ダウンロードしたコードを理解し、バグを修正することもできます。また理論的には、より優れたネズミ捕りを作ったり、ネズミ捕りでCPUを作ったりすることもできます。

Read next

ソフトウェア開発|Goのインライン最適化

この記事では、Go コンパイラーがどのようにインライン化を実装しているか、そしてこの最適化が Go コードにどのような影響を与えるかについて説明します。

Oct 13, 2025 · 7 min read