本文试图分析一个来在中国的Hou Qiming编写的一个科学计算器代码,看看它的真实面目是什么,以及它是如何工作的。关于这个程序的介绍请参阅http://www.ioccc.org/2011/hou/hint.html
原始的代码见下
#include <stdio.h> #include <math.h> #define clear 1;if(c>=11){c=0;sscanf(_,"%lf%c",&r,&c);while(*++_-c);}\ else if(argc>=4&&!main(4-(*_++=='('),argv))_++;g:c+= #define puts(d,e) return 0;}{double a;int b;char c=(argc<4?d)&15;\ b=(*_%__LINE__+7)%9*(3*e>>c&1);c+= #define I(d) (r);if(argc<4&&*#d==*_){a=r;r=usage?r*a:r+a;goto g;}c=c #define return if(argc==2)printf("%f\n",r);return argc>=4+ #define usage main(4-__LINE__/26,argv) #define calculator *_*(int) #define l (r);r=--b?r: #define _ argv[1] #define x double r; int main(int argc,char** argv){ if(argc<2){ puts( usage: calculator 11/26+222/31 +~~~~~~~~~~~~~~~~~~~~~~~~calculator-\ ! 7.584,367 ) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+ ! clear ! 0 ||l -x l tan I (/) | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+ ! 1 | 2 | 3 ||l 1/x l cos I (*) | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+ ! 4 | 5 | 6 ||l exp l sqrt I (+) | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+ ! 7 | 8 | 9 ||l sin l log I (-) | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~(0 ); } return 0; }
采用GCC 对原始代码进行预处理,并重新编排格式,得到功能等价的代码如下。
#include <stdio.h> #include <math.h> double r; int main(int argc,char** argv) { if(argc<2) { if(argc==2) printf("%f\n",r); return argc>=4+ 0; } { double a; int b; char c; c= (argc<4?main(4-21/26,argv): *argv[1]*(int) 11/26+222/31 + *argv[1]*(int)- !7.584)&15; b=(*argv[1]%21 +7)%9*(3*367>>c&1); c+= !1; if(c>=11) { c=0; sscanf(argv[1],"%lf%c",&r,&c); while( *++argv[1]-c); } else if ( argc>=4 && !main ( 4- ( *argv[1]++=='('),argv) ) argv[1]++; g: c+= ! 0 || (r); r=--b? r: - (r); r=--b? r: tan (r); if (argc<4&&*"/"==*argv[1]) { a=r; r=main(4-23/26,argv)? r*a: r+a; goto g; } c=c |! 1 | 2 | 3 || (r); r=--b?r: 1/ (r); r=--b?r: cos (r); if (argc<4&&*"*"==*argv[1]) { a=r; r=main(4-25/26,argv)?r*a:r+a; goto g; } c=c | !4 | 5 | 6 || (r); r=--b ? r: exp (r); r=--b ? r: sqrt (r); if (argc<4&&*"+"==*argv[1]) { a=r; r=main(4-27/26,argv) ? r*a : r+a; goto g; } c=c | ! 7 | 8 | 9 ||(r); r=--b? r: sin (r); r=--b? r: log (r); if (argc<4 && *"-" == *argv[1] ) { a=r; r=main(4-29/26,argv)?r*a:r+a; goto g; } } if(argc==2) printf("%f\n",r); return argc>=4+0; }
可以看出,这个程序是一个递归程序,main函数反复的调用自己,将计算结果存入全局变量r,当所有计算完成后,打印计算结果。限于时间的关系,这里暂不分析其工作原理,等以后有时间再作分析。