1. 程式人生 > >1987年國際C語言混亂代碼大賽獲獎的一行代碼

1987年國際C語言混亂代碼大賽獲獎的一行代碼

做了 代碼 pan 執行 轉換成 ng- ref bat 位置

技術分享


macb() ?

lpcbyu(&gbcq/_\021%ocq\012\0_=w(gbcq)/_dak._=}_ugb_[0q60)s+


這是CoolShell博主之前做了一個非常有意思的在線puzzle,仿照一些前端過關的遊戲,做了幾個和程序猿有關的迷題,一個通關遊戲。這個事測試的第二題。並為通關的前十名送上《Unix環境高級編程(第三版)》(感謝

from=feed&loc=at" style="color:#6c6351">@出版圈郭誌敏 贊助)或一個馬克杯(感謝@linux命令行精選網 贊助)

)這些謎題非常有趣同一時候也有一定的難度。因為水平有限,我並沒有通關。但我感覺這些東西確實非常有意思非常值得一做。還是能夠從中學到不少東西的。

這個是原遊戲測試的鏈接http://fun.coolshell.cn/。

這個測試我認為還是蠻有趣的。剛一進去看到頁面就懵了無從下手啊。限於個人能力及知識面狹窄,在作者的提示下了解到這是一段與Brainfuck編程語言有關的字段。網上一番搜索查看資料後,求解答到答案是“welcome.html”。

詳細求解實現過程看Brainfuck——讓你腦子淩亂的程序語言




一看到這個鍵盤就發現跟我們尋常鍵盤布局不一樣。於是就想到,這個題就是將圖中鍵盤的字符與我們電腦鍵盤上對應位置的字符替換。於是我非常快的做了。結果例如以下

main(){printf(&unix["\021%six\012\0"],(unix)["have"]+"fun"-0x60);}
 
看到這裏有點傻眼了,難道這就是傳說中的C語言混亂代碼。這是4th International Obfuscated C Code Contest (1987),由AT&T Bell Labs的David Korn所寫。

歷屆國際C語言混亂代碼大賽作品贊賞。將代碼COPY後粘貼到IDE裏面。編譯提示"unix was notdeclared in this scope"。

好吧,沒有聲明。那果斷的用#define宏定義個值唄

#define unix 1
尼瑪,竟然執行出結果unix。

這結果真是令人意向不到,混亂代碼就是一個字“亂”的有才。

通過查看相關資料。最後算是弄清了它的真面目了。


首先復習一點知識:

字符型常量和ASCII字符集。每一個字符在內存中占用一個字節,用來存儲它的ASCII碼值。因此。C語言的字符具有數值特征。能夠像整數一樣參加運算。

轉義字符:有一些字符,如回車符(‘\r‘),換行符(‘\n‘)等控制符號,它們不能在屏幕上顯示。也無法從鍵盤輸入,僅僅能用轉義字符表示。轉義字符由反斜杠加上一個字符或數字組成,它將反斜杠後面的字符或數字轉換成別的意義。

\ddd        1-3位八進制字符所代表的字符,如\102='B'    
\xhh        1-2位十六進制字符所代表的字符。如\x41='A'
printf("%x",'\n');printf("%x",'\r');//換行符。回車符的ASCII碼值分別為a,d,即十進制的10。13
最後。非常重要的一點啦
int a[3]={1,2,3};
printf("%d	%d\n",a[2], 2[a]);
//沒錯,你的眼睛卻是沒有看錯。他竟然真的都輸出是3</span>
以上翻閱自《C和指針》,arry[2]和2[arry]是等價的,這個詭異技巧之所以可行,源於C語言實現下表的方法。

盡管兩者並無區別但毫無疑問這樣影響程序的可閱讀性啦。不建議大面積推廣造成不必要的殺傷!

看到這裏,我們能夠將上面的翻譯過的那段代碼再度轉換一下,例如以下:

main(){printf(&unix["\021%six\n"],(unix)["have"]+"fun"-0x60);}	
//\021=17,ASCII字符為DC1。它是一個字符 ;\012=10=0xa='\n',\0='0'。則 
main(){printf(&"DC1%six\n\0"[unix],"have"[unix]+"fun"-0x60);}
//令unix=1。則
main(){printf(&"DC1%six\n"[1],"have"[1]+"fun"-0x60);}
//&"DC1%six\n",去字符串中下標1處的地址,則
main(){printf("%six\n",'a'-0x60+"fun");}
//a的ASCII僅僅為97=0x61,則
main(){printf("%six\n","fun"+1);}
以上等同main(){printf("%six\n","un");}
寫到這裏。整個過程應該非常清晰明確了。

OK,接著看下一題去



1987年國際C語言混亂代碼大賽獲獎的一行代碼