/ «2004-01-05 (Mon) ^ 2004-01-08 (Thu)» ?
   西田 亙の本:GNU 開発ツール -- hello.c から a.out が誕生するまで --

Categories Books | Hard | Hardware | Linux | MCU | Misc | Publish | Radio | Repository | Thoughts | Time | UNIX | Writing | プロフィール


2004-01-06 (Tue)

[Writing] Hello, world! 物語・その1

Hello, world! 再考

年明け早々、Hello, world! プログラムを再考してみる。次はあまりにも有名なプログラム hello.c だ。

#include <stdio.h>     // printf()

int main() {
  printf("Hello, world!?n");
  return 123;
 }

このぐらいであれば、最近の小学生でもコーディング出来てしまう内容だろう。ひょっとすると、チンパンジーでもできるかもしれない。お、天才チンパンジー愛ちゃんは、hello のビルドに成功したようである。

$ gcc -Wall -Os -o hello hello.c
$ wc -c hello
   4107 hello
$ ./hello ; echo $?
Hello, world!
123

オプション指定が、チンパンジーにしては、ちと出来すぎではあるが、hello はきちんと出来ておるぞ。お利口、お利口。実行結果も上々じゃ。親プロセスに返されたステータスコードも、$? できちんと確認できておるの。お母さん、愛ちゃんにバナナじゃ。

ウッキ〜〜!となったかどうかは知らないが、大変微笑ましい光景ではある。冗談はさておき、これと同じ情景が世界中のC言語入門書で何度となく繰り広げられてきた。まるで、定番の昼メロのように。

しかし、天の邪鬼の私はステレオタイプのドラマが大嫌いである。「こんな子供だましの説明で、本当に納得してええのか?」実は、この疑問こそが GCC プログラミング工房誕生のきっかけとなっている。

具体的に考えてみよう。日本で行われたCプログラミング講義の回数は、それこそ天文学的数字になるだろうが、この中で授業中に先生を困らせるような質問をした生徒が必ずいるはずである。もしくは、質問をする勇気はなくとも、心のどこかで教師の説明に納得がいなかった生徒が存在したことだろう。こんな風に。

「先生、僕がアセンブラで Hello, world! を書いたら、せいぜい数十バイトですけど、先生のプログラムはなんでそんなに馬鹿デカイんですかぁ?」

先生からすれば全く可愛げのないガキである。全体を重んじる先生は、オタクの生徒に付き合う余裕はないから、「そんな細かいこと言うとらずに、次のページめくってさっさと変数の章を読まんかね!」となるだろう。しかし、実はこの生徒こそが開発ツールの本質を見抜いているのである。

勇気あるオタク、A君が感じた疑問の正体は、gcc に -v (Verbose)オプションを与えることで垣間見ることができる。

$ gcc -Wall -Os -o hello hello.c -v 
Reading specs from /usr/local/gnu/lib/gcc-lib/i686-pc-linux-gnu/3.3.2/specs
Configured with: ../configure --prefix=/usr/local/gnu
Thread model: posix
gcc version 3.3.2
 /usr/local/gnu/lib/gcc-lib/i686-pc-linux-gnu/3.3.2/cc1 -quiet -v -D__GNUC__=3
-D__GNUC_MINOR__=3 -D__GNUC_PATCHLEVEL__=2 hello.c -quiet -dumpbase hello.c
-auxbase hello -Os -Wall -version -o /tmp/cc1nLUGT.s
GNU C version 3.3.2 (i686-pc-linux-gnu)
        compiled by GNU C version 2.95.4 20011002 (Debian prerelease).
GGC heuristics: --param ggc-min-expand=38 --param ggc-min-heapsize=15837
ignoring nonexistent directory "/usr/local/gnu/i686-pc-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/local/include
 /usr/local/gnu/include
 /usr/local/gnu/lib/gcc-lib/i686-pc-linux-gnu/3.3.2/include
 /usr/include
End of search list.
 /usr/local/gnu/lib/gcc-lib/i686-pc-linux-gnu/3.3.2/../../../../i686-pc-linux-gnu/bin/as -V -Qy
-o /tmp/cc0XPDJK.o /tmp/cc1nLUGT.s
GNU assembler version 2.14 (i686-pc-linux-gnu) using BFD version 2.14 20030612
 /usr/local/gnu/lib/gcc-lib/i686-pc-linux-gnu/3.3.2/collect2 --eh-frame-hdr -m elf_i386
-dynamic-linker /lib/ld-linux.so.2 -o hello /usr/lib/crt1.o /usr/lib/crti.o
/usr/local/gnu/lib/gcc-lib/i686-pc-linux-gnu/3.3.2/crtbegin.o -L/usr/local/gnu/lib/gcc-lib/
i686-pc-linux-gnu/3.3.2 -L/usr/local/gnu/lib/gcc-lib/i686-pc-linux-gnu/3.3.2/
../../../../i686-pc-linux-gnu/lib -L/usr/local/gnu/lib/gcc-lib/i686-pc-linux-gnu/3.3.2/
../../.. /tmp/cc0XPDJK.o -lgcc -lgcc_eh -lc
-lgcc -lgcc_eh /usr/local/gnu/lib/gcc-lib/i686- pc-linux-gnu/3.3.2/crtend.o /usr/lib/crtn.o

A君曰く、「訳わかんねぇ・・」。素直である。-v は gcc ドライバーによる、プリプロセッサー・Cコンパイラー・アセンブラ・リンカーの呼び出し状況を赤裸々に表示するためのオプションであるが、普段この工程はユーザーの目から隠匿されている。つまり、先ほどの先生も含め、ほとんどのプログラマーは目隠しをされながら、ビルド作業に専念していることになる。

残念ながら、私はこれまで「目隠しされている事実」を教えてくれる本に出会うことはなかったし、呪文にも等しい「gcc ドライバーによるビルド工程の詳細」を明らかにしてくれる資料も、見つけることはできなかった。

最近はインターネットが充実し、いかにも情報が充実しているように見える。しかし、人とは少し異なった視点から思索を深めるだけで、たちまち必要な情報が手元から逃げ去っていくことが分かる。私達が普段目にしているものは、実体のない「情報の蜃気楼」に過ぎないのである。

この情報砂漠において、頼れるものは自分の体と五感、そして自らの経験しかない。まずは、この事実を認めることから始めよう。