「先生,ちょっと聞いてもいいですか?」
「ん? 何か」
「Cでハローワールドを出すプログラムなんですが…」
「…」
「定数を使ってはいけない,ってルールなんですよ.あるところで話題になったんですが」
「研究室で?」
「じゃないんです.学外です」
「へえ,まいいや.定数ってのは…」
「数値,文字定数,文字列リテラル,こんなのはダメなんです」
「ふむ」
「先生だったら,それで,どうやってハローワールドを出しますか?」
「うーん,せやなあ,1文字ずつ,putcharで出力かなあ」
「1文字ずつ,ですか?」
「1文字ずつの値を求めるには,最低限ひとつ,変数がいるね」
「変数の初期化は,どないします?」
「んん…グローバル変数で初期化なしにすれば,ゼロになるよね」
「あ,そうですね」
「int c;とでもしてから,mainの中でc++;とすれば,cの値は1になって」
「はい」
「任意の回数だけインクリメントさせたら,任意の数にすることができて」
「ええ」
「あとは'H'の文字コードにしてから,putchar(c);,2番目の文字も以下同様,としたら,いけそうやね」
「…そのとおりです.なるほど.どうもありがとうございます」
「そんな,プログラミングのパズルかなんかが,あるんやね.面白いね」
「あ,そうだ先生,もう一つ,聞いていいですか」
「はいはい」
「先ほど,グローバル変数とおっしゃったじゃないですか」
「まあ,手軽やもんね」
「ローカル変数で,やっぱし定数なしで,ゼロにするにはどないします?」
「ん?」
「僕ね,こないしたんですよ.int c;だけだったら,何が入ってるか,わからないじゃないですか」
「まあねえ」
「それでね,そのあとにwhile(--c);って.これで,デクリメントを繰り返して,cが0になったらそこで抜けるんです」
「…え!?」
「おかしいですか?」
「いやあ,そんなことしなくても,c-=c;で0にならない?」
「あ,そうですねえ.そんな簡単な式で,できるんや!」
生成プログラムをRubyで
ラフスケッチ
Rubyの生成プログラムを書く前に,テキストエディタで作成したファイルです.
#include <stdio.h> int o; int a, b, c, d, e, f, g, h; main(void) { h++; /* 0x01 */ g = h + h; /* 0x02 */ f = g + g; /* 0x04 */ e = f + f; /* 0x08 */ d = e + e; /* 0x10 */ c = d + d; /* 0x20 */ b = c + c; /* 0x40 */ a = b + b; /* 0x80 */ /* "Hello, world!" */ putchar(b + e); /* H:0x48 */ putchar(b + c + f + h); /* e:0x65 */ putchar(b + c + e + f); /* l:0x6c */ putchar(b + c + e + f); /* l:0x6c */ putchar(b + c + e + f + g + h); /* o:0x6f */ putchar(c + e + f); /* ,:0x2c */ putchar(c); /* :0x20 */ putchar(b + c + d + f + g + h); /* w:0x77 */ putchar(b + c + e + f + g + h); /* o:0x6f */ putchar(b + c + d + g); /* r:0x72 */ putchar(b + c + e + f); /* l:0x6c */ putchar(b + c + f); /* d:0x64 */ putchar(c + h); /* !:0x21 */ puts((char *)&o); /* putchar(e + g); */ }
「Hello, world!」の16進ダンプは,「echo "Hello, world\!" | hexdump -C」というコマンドで求められます.