標準的 printf("Hello, World\\n"); 太無聊?以下六個 GCC 可編譯的 C 程式片段,用巨集、指標運算、goto、遞歸、位運算甚至純 +/- 組合,將「Hello, World」寫成令人嘆為觀止的混淆代碼。最後一個需 g++ 編譯,展示 C++ 編譯器的寬容度。
hello1.c#define _________ }
#define ________ putchar
#define _______ main
#define _(a) ________(a);
#define ______ _______(){
#define __ ______ _(0x48)_(0x65)_(0x6C)_(0x6C)
#define ___ _(0x6F)_(0x2C)_(0x20)_(0x77)_(0x6F)
#define ____ _(0x72)_(0x6C)_(0x64)_(0x21)
#define _____ __ ___ ____ _________
#include <stdio.h>
_____
層層巨集展開後還原為標準 main(){ putchar(0x48)... },純粹展示預處理器的圖靈完備性。
hello2.cmain(){
int x=0,y[14],*z=&y;
*(z++)=0x48; *(z++)=y[x++]+0x1D; *(z++)=y[x++]+0x07;
*(z++)=y[x++]+0x00; *(z++)=y[x++]+0x03; *(z++)=y[x++]-0x43;
*(z++)=y[x++]-0x0C; *(z++)=y[x++]+0x57; *(z++)=y[x++]-0x08;
*(z++)=y[x++]+0x03; *(z++)=y[x++]-0x06; *(z++)=y[x++]-0x08;
*(z++)=y[x++]-0x43; *(z++)=y[x]-0x21;
x=*(--z);
while(y[x]!=NULL) putchar(y[x++]);
}
利用陣列 y 就地構建 ASCII 碼,再反向列印,展示指標與陣列的深度綁定。
hello3.c#define __(a) goto a;
#define ___(a) putchar(a);
#define _(a,b) ___(a) __(b);
main(){ _:__(t)a:_('r',g)b:_('$',p)c:_('l',f)d:_(' ',s)e:_('a',s)
f:_('o',q)g:_('l',h)h:_('d',n)i:_('e',w)j:_('e',x)k:_('\n',z)
l:_('H',l)m:_('X',i)n:_('!',k)o:_('z',q)p:_('q',b)q:_(',',d)
r:_('i',l)s:_('w',v)t:_('H',j)u:_('a',a)v:_('o',a)w:_(')',k)
x:_('l',c)y:_('\t',g)z:___(0x0)}
將控制流完全扁平化為標籤跳轉,putchar 與 goto 交織,極難靜態分析。
hello4.cint n[]={0x48,0x65,0x6C,0x6C,0x6F,0x2C,0x20,0x77,0x6F,0x72,0x6C,0x64,0x21,0x0A,0x00},*m=n;
main(n){ putchar(*m)!='\0'?main(m++):exit(n++); }
利用 main 遞歸遍歷靜態陣列,n 參數被忽略(編譯器允許),以 exit 結束。
hello5.cmain(){ int i,n[]={(((1<<1)<<(1<<1)<<(1<<1)<<(1<<(1>>1)))+((1<<1)<<(1<<1))), ... }; for(i=0;i<14;i++) printf("%c",n[i]); }
每個字元皆由 1、<<、>>、+、- 組合而成,零字面常數,極致展示位運算表達能力。
hello6.cpp#define _(a) putchar(a);
main(){ int i=0; _(+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++i) ... }
利用大量 ++/-- 將 i 遞增至目標 ASCII 碼再輸出,需 C++ 編譯器支援長運算式。
Urban Müller 1993 年創建,僅八符號 > < + - . , [ ],操作位元組陣列與指標。Hello World:
++++++++++[>+++++++>++++++++++>+++>+<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.
附帶 50 行 ANSI C 解釋器原始碼,展示極簡語言實作之易。
僅由空白、Tab、換行組成,其他可見字元皆為註解。原始碼肉眼不可見,需 Ctrl+A 反白才能查看。
HAI CAN HAS STDIO? VISIBLE "HAI WORLD!" KTHXBYE
以貓咪網路用語為語法,極具娛樂性。
10 卜=0 / 20 入 水,火 / 30 從 日 = 水 到 火 ...回答 = 讀入('你認為中文程式語言有存在價值嗎 ?') / 如 回答 == '有': 寫 '好吧...'從混淆 C 代碼到極簡圖靈完備語言,再到梗文化與本土化程式語言,程式設計的邊界遠超乎想像。這些「無用」的探索,實則鍛鍊了對編譯器、執行模型與語法本質的深層理解——寫出能跑的代碼很容易,寫出讓人會心一笑的代碼才是藝術。