IOCCCコード解析その1

ちょこっとC言語のお勉強をかねて他人のすばらしい?コードを解析してみる。のんびりやっていこうかな〜

IOCCCのURL「http://www.ioccc.org/

1984年 「Dishonorable mention」受賞作品(anonymous.c)


int i;main(){for(;i["]
まあこんだけなんだけど〜何をやっているのかわからない。見にくいのでちょこっと整形。

int i;
main(){
for(
;
i["]
実際に上記まで整形するのに小一時間。for文がどこで分ければいいのやら意味不明だった。結構手こずったかな〜まあC言語あまり知らないでやろうとする無謀さが結構大好きです。

実際にコンパイルして走らせて見ると、予想通り「hello, world!」って文字列が表示される。何でだよオイ!

※注目1


read('-'-'-',i+++"hello, world!\n",'/'/'/')
まずはread関数。これはシステムコールじゃなくって実装しているって訳ね。システムコールと同じように書いているところがポイントなのでしょう。「'-'」はASCIIコードで45だっけ?まあ〜同じものから同じもの引いたら0だよね。次に「'/'」はASCIIコードで47、同じもの同士を割ったら1だ。ちなみに10進ね。

あとは i+++"hello, world!\n" ってところだけど、C言語では長いものに巻かれろって言われているので? i++ + "hello, world!\n" と分けるのが正解かな。

そうすると上記は
read(0, i++ + "hello, world!\n", 1)
となると思うのだが・・・どうよ。


次〜read関数部分


read(j,i,p)
{
write(j/p+p,i---j,i/i);
}
j = 0 固定なり同様にp = 1 固定なり、よって j/p + p = 0/1 + 1 = 1 で i/i = 同じもの割ってるんで = 1 となるかな〜

write(1, i-- - j, 1)
この write はシステムコールなんでしょうね。


ssize_t write(int fd, const void *buf, size_t count);

fd ... 書き込み先のファイルディスクリプタ
buf ... 書き込むデータが格納されているアドレス
count ... 書き込むデータサイズ(byte)

つ〜わけで、結局のところ標準出力に1byteづつ文字を出力するって事でいいのかな〜

はい!次


i++ + "hello, world!\n"
これってどういうこと?
array[9] ===> *(array + 9) ===> *(9 + array) ===> 9[array]
と言った変換が可能なんだよね。配列って結局、ポインタに置き換えられるらしい。コンパイルの際かな〜配列のあつかわれ方って結構不思議だよね。

と言う事で、i++ + "hello, world!\n" は "hello, world!\n"[i++] と同意。つまり、"hello, world!\n" の先頭アドレスを i++ しているわけです。一番最初は hello の e の部分のアドレスを指し示している。

受け側は、write(1, i-- - j, 1) となっており、i には送り側の「e」部分のアドレスが格納されているので、i-- で「h」のアドレスに移動して -j を行っているが j = 0 よりこの部分の減算は関係なし。

ふ〜文字列が表示される仕組みは理解できたんですけど、このまま行けばメモリの中身を全部吐き出してしまいそうなんですよね。for文のループ継続条件が意味不明。ここでも小一時間ほど悩みました。


i["]
これって良く見ると配列と思いませんか、で変換できそうです。
i["] "]