yuyixuantai的笔记 https://bbs.21ic.com/?476561 [收藏] [复制] [RSS] 我思,我在,我行于固件程序之旅

日志

国际混乱C语言大赛获奖作品解析示例(原创)

已有 4320 次阅读2008-4-6 20:35 |系统分类:原稿与翻译| 优秀代码, 混乱C, IOCCC

       国际混乱C语言大赛获奖的结果无疑是世界顶级C程序员C语言极限挖掘的结果。阅读,剖析它们绝对是一件超值的事情,下面我详细的剖析了一段在网上流传非常广的代码:


#include <stdio.h>
main(t,_,a)char *a;{return!0<t?t<3?main(-79,-13,a+main(-87,1-_,
main(-86,0,a+1)+a)):1,t<_?main(t+1,_,a):3,main(-94,-27+t,a)&&t==2?_<13?
main(2,_+1,"%s %d %d\n"):9:16:t<0?t<-72?main(_,t,
"@n'+,#'/*{}w+/w#cdnr/+,{}r/*de}+,/*{*+,/w{%+,/w#q#n+,/#{l+,/n{n+,/+#n+,/#\
;#q#n+,/+k#;*+,/'r :'d*'3,}{w+K w'K:'+}e#';dq#'l \
q#'+d'K#!/+k#;q#'r}eKK#}w'r}eKK{nl]'/#;#q#n'){)#}w'){){nl]'/+#n';d}rw' i;# \
){nl]!/n{n#'; r{#w'r nc{nl]'/#{l,+'K {rw' iK{;[{nl]'/w#q#n'wk nw' \
iwk{KK{nl]!/w{%'l##w#' i; :{nl]'/*{q#'ld;r'}{nlwb!/*de}'c \
;;{nl'-{}rw]'/+,}##'*}#nc,',#nw]'/+kd'+e}+;#'rdq#w! nr'/ ') }+}{rl#'{n' ')# \
}'+}##(!!/")
:t<-50?_==*a?putchar(31[a]):main(-65,_,a+1):main((*a=='/')+t,_,a+1)
  :0<t?main(2,2,"%s"):*a=='/'||main(0,main(-61,*a,
"!ek;dc
i@bK'(q)-[w]*%n+r3#l,{}:\nuwloca-O;m.vpbks,fxntdCeghiry"),a+1);}


(IOCCC 1988年获奖作品,作者 Ian Phillipps。)



       以上是完整的源代码,编译运行之后会产生意想不到的优美输出,然后,大多数人直接阅读上面的代码相当吃力,以下我逐步将上述的代码解析成为了我们熟悉的形式。



       首先是去除干扰项,将其中的两个字符串置换为宏,便于下一步分析:


#define USER_STRING_L \
"@n'+,#'/*{}w+/w#cdnr/+,{}r/*de}+,/*{*+,/w{%+,/w#q#n+,/#{l+,/n{n+,/+#n+,/#\
;#q#n+,/+k#;*+,/'r :'d*'3,}{w+K w'K:'+}e#';dq#'l \
q#'+d'K#!/+k#;q#'r}eKK#}w'r}eKK{nl]'/#;#q#n'){)#}w'){){nl]'/+#n';d}rw' i;# \
){nl]!/n{n#'; r{#w'r nc{nl]'/#{l,+'K {rw' iK{;[{nl]'/w#q#n'wk nw' \
iwk{KK{nl]!/w{%'l##w#' i; :{nl]'/*{q#'ld;r'}{nlwb!/*de}'c \
;;{nl'-{}rw]'/+,}##'*}#nc,',#nw]'/+kd'+e}+;#'rdq#w! nr'/ ') }+}{rl#'{n' ')# \
}'+}##(!!/"
#define USER_STRING_S \
"!ek;dc
i@bK'(q)-[w]*%n+r3#l,{}:\nuwloca-O;m.vpbks,fxntdCeghiry"


接下来是关键语句的置换,思路是:


某一行出现两个以上条件运算符号的时候
按照熟悉的
if (a)
 {}
else
 {}
格式
解析 (a)?(b):(c) 为
(a)?
 (b)
:
 (c) 


这样,


main(t,_,a)char *a;
{
return
 !0<t?
 (
  t<3?main(-79,-13,a+main(-87,1-_,main(-86,0,a+1)+a)):1,
  t<_?main(t+1,_,a):3,
  main(-94,-27+t,a)&&t==2?
  (
   _<13?main(2,_+1,"%s %d %d\n"):9
  )
  :
  (
   16
  )
 )
 :
 (
  t<0?
  (
   t<-72?
   (
    main(_,t,USER_STRING_L)
   )
   :
   (
    t<-50?
    (
     _==*a?putchar(31[a]):main(-65,_,a+1)
    )
    :
    (
      main((*a=='/')+t,_,a+1)
    )
   )
  )
  :
  (
   0<t?main(2,2,"%s"):*a=='/'||main(0,main(-61,*a,USER_STRING_S),a+1)
  )
 )
 ;
}
此时,代码的思路已经非常清晰了,但此函数在C语言级数上很难直接调试,相比于汇编级调试或者自己手动分析,再次转换代码是非常好的选择。
二次转换的核心思想如下:
将语句
return
(a)?
 (b)
:
 (c) 
转换为
if (a)
{
 rnt = (b);
}
else
{
 rnt = (c); 
}
二次转换之后的代码如下:


main (t,_,a)
char _;
char *a;
{
 int rnt;
 if (!0<t)
 {
  if (t<3)//t<3?main(-79,-13,a+main(-87,1-_,main(-86,0,a+1)+a)):1,
  {
   rnt = main(-79,-13,a+main(-87,1-_,main(-86,0,a+1)+a));
  }else
  {
   rnt = 1;
  }
  if (t<_)//t<_?main(t+1,_,a):3,
  {
   rnt = main(t+1,_,a);
  }else
  {
   rnt = 3;
  }
  if (main(-94,-27+t,a)&&t==2)
  {//rnt = (_<13?main(2,_+1,"%s %d %d\n"):9);
   if (_<13)
   {
    rnt = main(2,_+1,"%s %d %d\n");
   }else
   {
    rnt = 9;
   }
  }else
  {
   rnt = 16;
  }
 }else
 {
  if (t<0)
  {
   if (t<-72)
   {
    rnt = main(_,t,USER_STRING_L);
   }else
   {
    if (t<-50)
    {
     if (_==*a)
     {
      rnt = putchar(31[a]);
     }else
     {
      rnt = main(-65,_,a+1);
     }
    }else
    {
     rnt = main((*a=='/')+t,_,a+1);
    }
   }
  }else
  {//0<t?main(2,2,"%s"):*a=='/'||main(0,main(-61,*a,USER_STRING_S),a+1);
   if (0<t)
   {
    rnt = main(2,2,"%s");
   }else
   {
    rnt = (*a=='/'||main(0,main(-61,*a,USER_STRING_S),a+1));
   }
  }
 }
 return rnt;
}
到这里,你就可以单步调试来好好品位你这段代码了。


说明:


    文中的代码(源代码,剖析后代码)均可运行,我自己使用的编译环境是VC6.0。



 


路过

鸡蛋

鲜花

握手

雷人

发表评论 评论 (4 个评论)

访客Kpg6JV 2008-4-9 14:23
好爽的代码!!!够味!!!!
访客13YKc5 2008-4-9 15:22
代码和分析都很精彩
访客Mr2Tlx 2008-4-19 16:18
刚学C,不 怎么看懂,但是还 是很喜欢 C!~~~~ 很想学精,版主给电建议呢 !
答复 2008-9-23 14:55
't' : undeclared identifier