平々毎々(アーカイブ)

はてなダイアリーのアーカイブです。

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;
}

解説無かったらわかんないよ!