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


最近CoolShell博主做了一個很有意思的在線puzzle,這些謎題很有趣同時也有一定的難度。由於水平有限,我並沒有通關,我覺得這些題還是很值得一做的,從中可以學到很多東西。

例如其中的第二題:


題目中給出了一個鍵盤和一行看不懂的字符串。我們發現這個鍵盤的鍵盤布局和現在通用的鍵盤(QWERTY鍵盤)不一樣,它叫做Dvorak鍵盤。這里就不多作解釋了,詳細的可以去Google。鍵盤圖片明顯在提示我們:要通過兩種鍵盤的布局映射,將給出的字符串轉換成QWERTY鍵盤下的輸出。當然,你可以自己一對一寫出來,不過在線轉換工具更方便。

macb() ? lpcbyu(&gbcq/_\021%ocq\012\0_=w(gbcq)/_dak._=}_ugb_[0q60)s+
轉換之后得到:

main() { printf(&unix["\021%six\012\0"],(unix)["have"]+"fun"-0x60);}
這是1987年 國際C語言混亂代碼大賽(The International Obfuscated C Code Contest, IOCCC)一等獎的獲獎代碼,由貝爾實驗室的David Korn提交。當然平時我們不會寫出這么復雜難懂的代碼,但是分析這樣的代碼卻可以擴展我們的知識。

int main() 
{
	/* unix被編譯器內定為一個宏 
	 * 相當於#define unix 1     */
	
	printf("unix=%d\n", unix); /* =1 */	
	
	/* 打印字符串"un",因為"fun"是個字符數組
	 * "fun"+1相當於字符指針右移,指向"un" */
	printf("%s\n","fun"+1);

	/* "have"是個字符數組,"have"[1]即字符a
	 * 輸出97,即第二個字符'a'的ASCII值。*/
	printf("%d\n", "have"[1]);
	printf("%d\n", 'a');

	/* 在C語言中,x[1] = 1[x] */
	printf("%d\n", (1)["have"]);

	/* 97 - 96 = 0x61 - 0x60 = 1 */
	printf("%d\n", (1)["have"] - 0x60);

	/* 所以 "fun"+((1)["have"]-0x60) 相當於"fun"+1,輸出"un" */
	printf("%s\n", "fun" + ((1)["have"] - 0x60));

	/* 將其中的1用unix代替 */
	printf("%s\n", (unix)["have"]+"fun"-0x60);

	/* 以上為后半部分 = "un" */

	/* 下面兩個都輸出"bcde", 因為指針都是從'b'開始 */
	printf("%s\n", "abcde" + 1);
	printf("%s\n", &"abcde"[1]);

	/* &"abcde"[1] == &(1)["abcde"]  輸出一樣 */
	printf("%s\n", &(1)["abcde"]);

	/* 1用unix代替 */
	printf("%s\n", &unix["abcde"]);

	/* 下面輸出"%six" 並換行 */
	printf("%s", &"?%six\n"[1]);

	/* 注意:
	   \012 = 0x0a = \n, 
	   第一個字符 \021 被跳過
	   \0 是空字符  */

	/* 同樣輸出"%six" 並換行 */
	printf("%s", &"\021%six\012\0"[1]);

	/* 相當於這樣 */
	printf("%s", &unix["\021%six\012\0"]);

	/* 把字符串"%six\n"當作格式,輸出"ABix" */
	printf(&unix["\021%six\012\0"], "AB");

	/* 相當於這樣 */
	printf("%six\n", "AB");

	/* 所以下面的可以輸出"unix" */
	printf("%six\n", (unix)["have"]+"fun"-0x60);
	
	/* 至此,問題解決!!!輸出"unix" */
	printf(&unix["\021%six\012\0"],(unix)["have"]+"fun"-0x60);

	return 0;
}

這段代碼主要用到了x[a]和指針運算的一些知識,相信上面的步驟和注釋已經很清楚了,最終結果就是輸出unix





免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM