2013-08-02 1 views
0

다음 프로그램이 어떻게 작동하는지 이해하려고 노력하고있었습니다. 명령 행 과학 계산기입니다. 출처는 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; 
} 

그것은 -Wall와 GCC 4.7.2 (리눅스)에 경고없이 컴파일합니다. 나는 그것을 단순화하려고 시도했지만, 아래에 주어진 약간 수정 된 형태에 대한 모든 추가 변경은 예기치 않은 결과 (잘못된 결과)를 만들어 내기 시작한다.

#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; 
} 

누군가가 어떻게 작동하는지 설명해주세요.

+4

이 소스 코드의 전처리 된 형태를 연구하십시오. 아마도'gcc -C -E obfusc.c | grep -v '^ #'| indent> obfusc.i' 그러면'obfusc.i' 내부를 보게됩니다. –

+4

확실히 아닙니다. IOCCC 항목을 분석하는 데 적어도 2 시간이 걸립니다 (코드가 무엇을하는지 이해하려고 시도하는 과정에서 코드를 완전히 리팩토링합니다). 그리고 긴 설명은이 사이트의 범위를 완전히 벗어나 작성하는 데 하루가 걸릴 것입니다. IMHO. – cmaster

+0

'__LINE__' 매크로는 줄 바꿈에 민감합니다. 이것은'/ * + -'연산자를 식별하는 데 사용됩니다. – ugoren

답변

4

은 다음과 같이 확장되어 :

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 = (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; 
     } 
    c = c | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~(0); 
    } 
    if (argc == 2) 
    printf ("%f\n", r); 
    return argc >= 4 + 0; 
} 

그것은 아직 정확하게 읽을 수 있지만, 적어도 지금은 아무것도 당신에게서 숨겨 것 아니다. 그렇게 심하게 물지 않고 단순화를 할 수 있어야합니다.

@cmaster와 같은 이유로 완전한 설명을 듣지는 않을 것입니다.

관련 문제