トリッキーコードネット トップへ戻る   C/C++, Java, Perl, PHP, JavaScript, アルゴリズム, ショートコーディング, IOCCCコードの解説, 等々

サイト情報

トリッキーなコード

7行プログラミング

物凄いコード集

アルゴリズム

データ構造

C/C++な話題

コードサンプル

ツール/環境構築

開発ノウハウ 等

ネタ/ジョーク集

おススメ書籍/サイト

サイトTOP >> 物凄いコード集 >> 「Unix」の表示 (C言語)

"unix"の表示 (C言語 - IOCCC)

void main(void) {printf(&unix["\021%six\012\0"], (unix)["have"]+"fun"-0x60);}
↑のコードは、コンパイルして実行すると、"unix"と表示されます。(∩´∀`)∩(´∀`)∩(´∀`∩)ワショーイ!! このコードは、1987年のIOCCC優勝作品でもあり、WikipediaのIOCCC項目で、一番最初に表示されているコードです。 また、こちらでは、より詳細にこのコードの解説をされている方がいるので、参考にして下さい^^;) 上記リンク先がなくなっていたので、私がコードの解説を書きます。 コードの解説に先立ち、もし上記コードをWindowsにて実行する場合は、 以下の様にコード先頭に「#define unix 1」を書いてやる必要があります。 (∵ Unix環境では、unix が 1 と定義されている為)
#define unix 1
void main(void) {printf(&unix["\021%six\012\0"],(unix)["have"]+"fun"-0x60);}
さて、ではこのコードを、VC++2005で実行してみます。 以下の様な警告がでますが、コンパイルは可能です。 「warning C4013: 関数 'printf' は定義されていません。int 型の値を返す外部関数と見なします。」 実行結果は以下の通り IOCCC-unix それでは、コードを読み解いて行きます。 まず、コードに適当な改行、インデントを入れます。そして、警告がうるさいのでstdio.hをインクルードします。
 1 : #include <stdio.h>
 2 :
 3 : #define unix 1
 4 :
 5 : void main(void)
 6 : {
 7 :     printf(
 8 :         &unix["\021%six\012\0"],
 9 :         (unix)["have"] + "fun" - 0x60
10 :         );
11 : }
そして、定義済のunixを1に置換します。
#include <stdio.h>

void main(void)
{
    printf(
        &1["\021%six\012\0"],
        (1)["have"] + "fun" - 0x60
        );
}
そして、i["hogehoge"] が "hogehoge"[i] と同義だという、C言語の摩訶不思議な交換法則を適応します。
1 : #include <stdio.h>
2 :
3 : void main(void)
4 : {
5 :     printf(
6 :         &"\021%six\012\0"[1],
7 :         "have"[1] + "fun" - 0x60
8 :         );
9 : }
さて、6行目はprintf()関数の第一パラメータであり、ここには char *が入ります。 "\021%six\012\0"という文字列の2文字目(配列は0-baseである事に注意)のアドレスを渡している為、 6行目全体は以下の文字列に置き換えられます。
"%six\012\0",
「%s」は、パラメータの文字列を差し込む位置、 「\012」は、8進数で「10」を表しており、これはアスキーコード表と照らし合わせると「\n(改行)」だと分かります。 「\0」は、おなじみのナル文字です。 これらを考慮し、最終的に6行目は、以下の様に置き換わります。
"%six\n",
つまり、冒頭のコード全体では、以下の様に置き換わります。
1 : #include <stdio.h>
2 :
3 : void main(void)
4 : {
5 :     printf(
6 :         "%six\n",
7 :         "have"[1] + "fun" - 0x60
8 :         );
9 : }
次に、7行目を解析します。 「"have"[1]」の部分は、「'a'」を指しており、「'a'」をアスキーコード表を元に10進数に直すと「97」です。 そして、16進数表記の「0x60」を10進数に直すと「96」です。 つまり7行目は以下の様に置き換えられます。
97 + "fun" - 96
これは
"fun" + 1
ということであり、"fun"の2文字目のアドレスを指す事になります。つまり "un"のアドレスです。 以上を整理すると、冒頭のコードは
#include <stdio.h>

void main(void)
{
    printf(
        "%six\n",
        "un"
        );
}
となり、めでたく「unix」と表示される理由が判明しました~~♪^^;)
         このエントリーをはてなブックマークに追加   


作業効率化・ライフハックのオススメ記事




コンピュータ・テクノロジーのオススメ記事





恋愛・人間関係のオススメ記事




※ 当サイトは、トップページからリンクで辿る事の出来るページに限り、リンクフリーです。
※ 当サイトの閲覧/利用によって生じた如何なる損害も、当サイト管理人は責任を負いません。
※ 当サイトの内容を転載される場合は、当サイトへのリンクをお願い致します。