首页 > 代码库 > 1987年国际C语言混乱代码大赛获奖的一行代码

1987年国际C语言混乱代码大赛获奖的一行代码

             技术分享


                    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语言混乱代码大赛获奖的一行代码