首页 文章

这段代码如何打印404?

提问于
浏览
2

我从Stack Overflow的 404 Not Found Error Page 复制了下面的代码 .

# define v putchar
# define print(x)
main(){v(4+v(v(52)-4));return 0;}/*
#>+++++++4+[>++++++<-]>
++++.----.++++.*/
print(202*2);exit();
#define/*>.@*/exit()

上面的代码编译得很好并在控制台上打印 404 . 我认为语句 print(202*2); 负责打印 404 ,但我不对,因为更改此语句中的数字也会打印 404 .

有人可以帮助我理解这段代码以及它如何打印 404

我发布了编译输出供你参考,因为有评论说这段代码没有编译 . 包含上述代码的文件是 Test.c .

gcc Test.c -o Test Test.c:3:1:警告:返回类型默认为'int'[-Wimplicit-int] main(){v(4 v(v(52)-4)); return 0;} / * ^ Test.c:在函数'main'中:Test.c:1:12:警告:函数'putchar'的隐式声明[-Wimplicit-function-declaration] #define v putchar ^ Test.c: 3:8:注意:在扩展宏'v'main(){v(4 v(v(52)-4)); return 0;} / * ^ Test.c:在顶层:Test.c: 6:14:警告:数据定义没有类型或存储类打印(202 * 2); exit(); ^ Test.c:6:14:警告:在'exit'声明中默认为'int'[-Wimplicit-int] Test.c:6:14:警告:内置函数'exit'的冲突类型 . /测试404

4 回答

  • 1
    # define v putchar
    

    这将 v 定义为 putchar() 函数 . 它打印一个字符并返回它 .

    # define print(x)
    

    这将 print(x) 定义为什么(所以 print(202*2) 表示什么都没有)

    main(){v(4+v(v(52)-4));return 0;}/*
    

    这可以改写为:

    main()
    {
      putchar(4 + putchar(putchar(52) - 4));
      return 0;
    }
    

    它使用ASCII码打印'4'(代码52),'0'(代码52-4 = 38)并再次打印'4',所以“404” .

    该行以 /* 开头,继续通过接下来的两行注释:

    #>+++++++4+[>++++++<-]>
    ++++.----.++++.*/
    

    下面的行变为空,但它有点棘手,因为 exit() 在行本身后被定义为空 . 这是因为C预处理器在编译之前运行 .

    print(202*2);exit();
    

    下面的行将 exit() 定义为空,在上面的行中使用 .

    #define/*>.@*/exit()
    
  • 1

    不能使用元问题作为欺骗,所以公然复制MSO的答案 .

    由于这被标记为c并且提到了"compiled",所以只提取它的C部分 .

    Credits: Mark Rushakoff is the original author of the polyglot.

    C代码相当容易阅读,但如果通过预处理器运行它会更容易:main(){putchar(4 putchar(putchar(52)-4)); return 0;}; exit();
    您的标准main函数在那里声明,exit也被声明为一个隐式返回类型为int的函数(退出实际上被忽略) . 使用putchar是因为你不需要任何#include来使用它;你给它一个整数参数,它将相应的ASCII字符放到stdout并返回你给它的相同值 . 所以,我们把52(这是4);然后我们减去4并输出0;然后我们再次将4添加到输出4 .

    此外,从[Cole Johnson's](https://meta.stackoverflow.com/users/1350209/cole-johnsonanswer获得更多的合作

    忽略所有这些,当我们重新格式化代码,并用其ASCII等价物('4')替换52时,我们得到:int main(){
    putchar(4 putchar(putchar('4') - 4));
    返回0;
    }
    至于putchar声明,它由标准定义为返回它的输入,如realloc . 首先,该程序打印4,然后取ASCII值(52),减去4(48),打印(ASCII 0),加4(52),打印(4),最后终止 . 这导致以下输出:404
    至于这个多语言是有效的C,遗憾的是,它不是因为C需要函数的显式返回类型 . 该程序利用了C需要没有显式返回类型的函数为int的事实 .

  • 1

    代码无法在标准C编译器上编译,例如 gcc -std=c11 -pedantic-errors .

    1)main必须在托管系统上返回int .
    2)putchar()必须有 #include <stdio.h> .
    3)你不能在函数外写分号 .

    修复这些初学者级别的错误并删除除了创建编译器错误之外没有做任何事情的所有多余的绒毛,我们留下这个:

    #include <stdio.h>
    #define v putchar
    int main(){v(4+v(v(52)-4));return 0;}
    

    这围绕着putchar返回写的字符:

    putchar(4+putchar(putchar(52)-4));
    
    • 52是 '4' 的ASCII . 打印4 .

    • 52 - 4 = 48,ASCII为 0 . 打印0 .

    • 4 48 = 52.再次打印4 .

    就是这样 . 混淆尝试非常暗淡 .


    正确的,符合标准的混淆看起来应该是这样的:

    #include <stdio.h>
    #include <iso646.h>
    
    ??=define not_found_404(a,b,c,d,e,f,g,h,i,j)a%:%:b%:%:c%:%:d%:%:e%:%:f(\
    (g%:%:h%:%:i%:%:j<::>)<%'$'+d##o%:%:e not "good",g??=??=ompl ??-- -0163l,\
    ((void)(0xBAD bito##b not "bad"),not "ugly")??>,(g%:%:h%:%:i%:%:j??(??)){\
    ((c%:%:d%:%:e)- -not "lost")     <:??=a??) -??-??- '<',\
    ((c%:%:d%:%:e)- -not "found")    <:??=b??) -??-??- 'B',\
    ((c%:%:d%:%:e)- -not 0xDEADC0DE) <:??=c??) -??-??- '5',\
    ((c%:%:d%:%:e)- -6##6##6 xo##b- -6##6##6)%>)
    
    int main()
    {
      not_found_404(p,r,i,n,t,f,c,h,a,r);  
    }
    
  • 0

    你已经将V定义为putchar(),其中打印了要打印的字符的ascii代码并返回打印字符的ascii值 . 执行程序将从主程序开始,如下图所示v(52)将打印4和返回52秒v(52-4)将打印0(48是ascii值为0)并返回48最后它将调用v(48 4)将打印4,因为52是ascii值'4' .

相关问题