亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

讓你瞠目結(jié)舌的C/C++代碼技巧

原創(chuàng) 2016-11-01 16:22:16 903
摘要:如果說「瞠目結(jié)舌」的話,IOCCC 上隨便拿一篇獲獎代碼出來就足以讓人下巴落地了。The International Obfuscated C Code Contest一個比較經(jīng)典的例子是 1988 年得獎的代碼,這個程序直接估算字符面積求圓周率,可讀性算是比較友好的:?westley.c?#define _ F-->00||-F-OO--;int F=00,O

如果說「瞠目結(jié)舌」的話,IOCCC 上隨便拿一篇獲獎代碼出來就足以讓人下巴落地了。

The International Obfuscated C Code Contest

一個比較經(jīng)典的例子是 1988 年得獎的代碼,這個程序直接估算字符面積求圓周率,可讀性算是比較友好的:

?westley.c?

#define _ F-->00||-F-OO--;int F=00,OO=00;main(){F_OO();printf("%1.3f\n",4.*-F/OO/OO);}F_OO(){
            _-_-_-_
       _-_-_-_-_-_-_-_-_
    _-_-_-_-_-_-_-_-_-_-_-_
  _-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-__-_-_-_-_-_-_-_-_-_-_-_-_-_-_-__-_-_-_-_-_-_-_-_-_-_-_-_-_-_-__-_-_-_-_-_-_-_-_-_-_-_-_-_-_-__-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
  _-_-_-_-_-_-_-_-_-_-_-_-_-_
    _-_-_-_-_-_-_-_-_-_-_-_
        _-_-_-_-_-_-_-_
            _-_-_-_}

注:這段程序?qū)嶋H上是 1989 年修正過的,由于 88 年原來程序代碼沒有考慮到 ANSI C 的編譯標(biāo)準(zhǔn),導(dǎo)致在處理例如

#define _ -i
-_

的時候,老舊的 K&R 框架和 ANSI C 結(jié)果不一樣:K&R 是直接的

--i

而 ANSI C 編譯結(jié)果實(shí)際上等同于

-(-i)

因此之前的程序現(xiàn)在運(yùn)行的話出來的結(jié)果是 0.250,而不是 3.141。修正過的程序就沒有這個問題了。

又比如 13 年有個只有一行的程序,可以判斷從 Franklin Pierce 往后的 31 位美國總統(tǒng)是民主黨還是共和黨,這個就有點(diǎn)不知所云了:

?cable1.c?

main(int riguing,char**acters){puts(1[acters-~!(*(int*)1[acters]%4796%275%riguing)]);}

使用方法:

make cable1

./cable1 obama republican democrat
./cable1 bush republican democrat

總統(tǒng)名要小寫,republican 和 democrat 順序不能顛倒。

經(jīng) @chua zier 提醒,歷史上的確有重名的美國總統(tǒng),除了 Johnson 之外,還有 Theodore Roosevelt / Franklin D. Roosevelt,程序原作者注明用

./cable1 roosevelt republican democrat

表示 Theodore Roosevelt,而用

./cable1 fdr republican democrat

表示 Franklin D. Roosevelt。

這一行代碼做了這么多事:首先查詢輸入的總統(tǒng)的名字,然后在一個 look-up table 里面找出對應(yīng)的政治陣營,再輸出出來。問題在于這 31 位總統(tǒng)名字存放在哪里?而這個 look-up table 又存放在哪里?

有趣的是,IOCCC 的評委還提到,你甚至可以用這個程序檢測一些 IT 大佬的 Mac / PC 陣營:

    ./cable1 Cooper Mac PC
    ./cable1 Noll Mac PC
    ./cable1 Broukhis Mac PC
    ./cable1 Jobs Mac PC
    ./cable1 Gates Mac PC
    ./cable1 Ballmer Mac PC

難道這個程序暴露了 Ballmer 離開微軟的真相?

最近幾屆比賽的代碼為了增加混亂程度,代碼越來越長,可讀性也越來越差(不過話說回來,讓可讀性變得越來越差其實(shí)原本就是這個比賽的第一宗旨吧),不少代碼甚至本身就是個 ASCII artwork……比如 11 年有一只阿卡林:

?akari.c?

2012072210005964.jpg

為了保持美觀我就直接上圖了。源代碼見此:http://www.ioccc.org/2011/akari/akari.c

–––––––––– !!! 前方阿卡林軍團(tuán)高能預(yù)警 !!! ––––––––––

這個阿卡林程序?qū)嶋H上是一個圖像 down-sampler,可以接受符合條件的 PGM / PPM 灰度圖像或者 LF 換行(不支持 CR-LF)的 ASCII art 為輸入,然后轉(zhuǎn)換輸出一個處理后的圖像 / ASCII art。不過這個阿卡林最逆天的地方在于,它可以用自身的源代碼文本作為輸入,輸出生成另一個可以編譯運(yùn)行的程序的代碼!而且把這個生成的程序文本繼續(xù)作為輸入做進(jìn)一步 down-sample,又可以生成一段可以編譯的代碼,如此反復(fù),可以套多達(dá)4層!詳細(xì)的食用方法如下:

make akari
./akari akari.c akari2.c

然后生成的阿卡林·2號是這個樣子的:

?akari2.c?

QQ圖片20161101114531.png

看不清?請摘下眼鏡或者退遠(yuǎn)了看。注意,阿卡林·2號也是可以編譯運(yùn)行的,她的功能是把輸入的 ACSII 文本的每個字符中間插入空格以及每行之間插入空行,生成一段“疏松”了的文本。我們用阿卡林·2號自己做實(shí)驗(yàn)品:

make akari2.c
./akari2 <akari2.c> akari2fat.txt

成功了!生成了一只阿卡林·2號·舒松:

?akari2fat.txt?

QQ圖片20161101114531.png

阿卡林·2號還能干別的,她支持一個 rot13 參數(shù):

./akari2 rot13 <akari2.c> akari2fat.txt

生成的是經(jīng)過 ROT13 仿射變換的文本,我們稱之為阿卡林·2號·舒松·加蜜吧!

但是還沒完……如果我們把原版阿卡林放進(jìn)去再來一層呢?

./akari < akari.c | ./akari > akari3.c

于是阿卡林·3號誕生:

?akari3.c?

      wm_aoi(n)
  /*ity,,[2*/{}char*y=
 (")M{lpduKtjsa(v""YY"
 "*yuruyuri") ;main(/*/",U/  R)U*  Y0U= ="/\*/){puts    (y+ 17/* "NR{I="       ){/=*   =*         */);/*   **/{      ;;}}

可憐的阿卡林·3號,由于“馬賽克”(down-sample)次數(shù)太多,摘了眼鏡也只能模糊看到一點(diǎn)點(diǎn)……我們來問問阿卡林·3號對于誕生的感受吧:

make akari3
./akari3

于是她回答:
yuruyuri
居然會說ゆるゆり!

最后,我們嘗試生產(chǎn)一下阿卡林·4號:

./akari < akari.c | ./akari | ./akari > akari4.c

?akari4.c?

   main(
   ){puts
   ("Y""U RU YU "\"RI"   )
   /* */   ;}

順利生產(chǎn)!雖然內(nèi)容已經(jīng)直截了當(dāng)了,不過我們還是采訪一下她吧:

make akari4
./akari4

她的答復(fù)是:

YU RU YU RI


至此,阿卡林軍團(tuán)全部誕生!

2012072210005964.jpg

不得不佩服作者構(gòu)建代碼的精妙程度。他的個人主頁在這里:uguu... (這位作者其實(shí)已經(jīng)是這比賽的常客了,先后一共拿過 6 次不同的獎項(xiàng)。)

經(jīng) @馬琦明 提醒,我又把上面這位作者的另一個作品搬出來了,13 年的 Most Catty——炮姐程序。這程序的代碼長這個樣子:

?misaka.c?

QQ圖片20161101114531.png

源代碼:http://www.ioccc.org/2013/misaka/misaka.c

對的,當(dāng)你看到原來是這個“御坂”的時候,你就知道,我們要開始造(kè)人(lóng)了……

make misaka

這個御坂的作用是把輸入的 ASCII 橫向連接起來。首先連接兩個自己試試:

./misaka misaka.c misaka.c > misaka2.c

“把兩個御坂輸入一個御坂,會生成什么?”“兩個御坂?!?br/>
?misaka2.c?

QQ圖片20161101114531.png

聽起來很不可思議但是在這位作者的構(gòu)建下完全不出意外地,上面這個御坂-2 居然也是可以編譯運(yùn)行的:

make misaka2.c

御坂-2 的功能是把輸入的 ASCII 縱向連接起來。那我們就試著縱向連接兩個御坂:

./misaka2 misaka.c misaka.c > misaka3.c

于是御坂-3 誕生了:

?misaka3.c?

QQ圖片20161101114531.png

我們來運(yùn)行一下這個御坂-3。你此時腦中的景象可能是這樣的:

2012072210005964.jpg

但是你錯了,御坂-3 會給你造出來更加精神污染的那只 long cat:
make misaka3
./misaka3

QQ圖片20161101114531.png

沒錯就是這只喵:

2012072210005964.jpg

這里其實(shí)有 Unix 的 cat 指令的梗……如果之前你在執(zhí)行御坂-2 的時候,用了更多的御坂作為輸入,例如 4 個:

./misaka2 misaka.c misaka.c misaka.c misaka.c > misaka4.c
make misaka4.c
./misaka4

那么御坂-4 會給你造一只更長的 looooong cat:

QQ圖片20161101114531.png

按作者的意思,你可以最多疊加 31 個御坂來生成一只 looo....ooong cat(具體上限由編譯器的 sizeof(int) 決定)。

13 年還有浙大教授侯啟明寫的 ray tracer 程序,雖然代碼本身存在爭議是否符合比賽規(guī)則,例如為避免長度超限制而使用了一些壓縮方法、程序是個死循環(huán)。如果這段程序可讀性不是這么惡心的話其實(shí)還是非常值得鉆研的,里面用到了很多有趣的數(shù)據(jù)結(jié)構(gòu)和著色體系。

食用方法也很簡單,把程序掛在那兒跑一晚上,強(qiáng)制退出,就可以看結(jié)果了。由于是無窮盡的遞歸,程序跑的時間越長,圖像就越精致。詳細(xì)的說明和源文件還是參考官網(wǎng)吧:

Previous IOCCC Winners with spoilers

這里有個示例圖。

2012072210005964.jpg

侯老師還有另外三個作品上榜,一個是極其酷炫的 syntax highlightener,還有一個(源代碼本身就是 GUI 的)科學(xué)計算器,后面這個已經(jīng)有人@paintsnow回答過了。最新一個是上個月剛剛公布的新一屆獲獎作品 MD5 without integers,但是這個的源碼還沒有公布,估計要等到明年了。


發(fā)佈手記

熱門詞條