【发布时间】:2013-08-03 17:55:46
【问题描述】:
我试图了解以下程序是如何工作的。它是一个命令行科学计算器。来源取自here。对于 IOCCC 条目来说,它似乎很可读,但显然不是。
#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 4.7.2 (Linux) 上使用 -Wall 编译而没有警告。我试图简化它,但是对下面给出的稍微修改的形式进行任何进一步的更改都会产生意想不到的结果(不正确的输出)。
#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 -C -E obfusc.c | grep -v '^#' | indent > obfusc.i然后看里面̀obfusc.i -
当然不是。 IOCCC 条目至少需要我两个小时来分析(我会在试图理解它的作用的过程中完全重构代码),而冗长的解释可能需要一天的时间来编写,并且完全超出了本网站的范围恕我直言。
-
注意
__LINE__宏,它对换行很敏感。用于标识/*+-运算符。
标签: c obfuscation