IOCCC 1987 by David Korn
kshの人のワンライナーの仕組みを今日初めて知った。そっか、こういう仕組みか!
#include <stdio.h>
int main()
{
mainの最初に(暗黙に)定義されたint変数
ANSI CじゃなくてK&R Cなのがポイント。つまりargc、すなわち起動パラメータが無ければ1
printf("unix=%d\n", unix);
文字列の先頭アドレスをインクリメントするので"un"が表示される
printf("%s\n","fun"+1);
2文字目がintとして評価されるから97
printf("%d\n", "have"[1]);
上はこれと等価
printf("%d\n", 'a');
x[y] = *(x+y) = y[x] だから、こうも書ける
printf("%d\n", (1)["have"]);
97 - 96 = 1
printf("%d\n", (1)["have"] - 0x60);
第2引数は"fun" + 1 と等価だから'un'が表示される
printf("%s\n", "fun" + ( (1)["have"] - 0x60) );
括弧をとって、変数unixを使った。これも等価
printf("%s\n", (unix)["have"]+"fun"-0x60);
さて、これは'bcde'が表示される
printf("%s\n", "abcde" + 1);
こうも書ける。この場合&には意味がない
printf("%s\n", &"abcde"[1]);
これも等価
printf("%s\n", &(1)["abcde"]);
括弧をはずしたが、優先順位があるので結果は変わらず
printf("%s\n", &unix["abcde"]);
2文字目から表示。だから'%six'+改行文字
printf("%s", &"?%six\n"[1]);
2文字目から表示。だから'%six'+改行文字(\012)。最後の\0は無視される
printf("%s", &"\021%six\012\0"[1]);
これも等価。'%six'+改行文字(\012)
printf("%s", &unix["\021%six\012\0"]);
上をフォーマット文字列に使ったので、'ABix'+改行文字が表示される
printf(&unix["\021%six\012\0"], "AB");
やってることはこれと一緒
printf("%six\n", "AB");
じゃあ、"AB"のかわりに"un"を使えば
printf("%six\n", (unix)["have"]+"fun"-0x60);
"unix"が表示されるじゃないか
printf(&unix["\021%six\012\0"],(unix)["have"]+"fun"-0x60);
return 0;
}
解説無かったらわかんないよ!