本文试图分析一个来在中国的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,当所有计算完成后,打印计算结果。限于时间的关系,这里暂不分析其工作原理,等以后有时间再作分析。