这段代码如何打印404?

时间:2017-06-28 05:52:53

标签: c gcc

我在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 。我认为声明打印(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));返回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 个答案:

答案 0 :(得分:1)

不能使用元问题作为欺骗,因此公然从the MSO answer复制。

由于这是标记为并且已提及&#34;已编译&#34;,因此只需提取其中的C部分。

致谢:Mark Rushakofforiginal author of the polyglot

  

C代码相当容易阅读,但如果运行它会更容易   通过预处理器:

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

您的标准main函数已在此处声明,exit也是   声明为隐式返回类型为int的函数(exit   实际上被忽略了。)

     使用

putchar是因为您不需要任何#include来使用它;   你给它一个整数参数,它放置相应的ASCII   字符到标准输出并返回您给它的相同值。所以,我们   放52(4);然后我们减去4并输出0;然后我们补充说   4再次输出4

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

  

忽略所有这些,当我们重新格式化代码并替换时   52及其ASCII等价物('4'),我们得到:

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

至于putchar声明,它由标准定义   返回它的输入,例如realloc。首先,该程序打印4,   然后取ASCII值(52),减去4(48),打印出来   (ASCII 0),添加4(52),打印(4),最后   终止。这导致以下输出:

404
     

至于这个多语言是有效的 C ++ ,不幸的是,它不是    C ++ 需要函数的显式返回类型。该程序利用了 C 需要没有的功能的事实   显式返回类型为int

答案 1 :(得分: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码打印&#39; 4&#39; (代码52),&#39; 0&#39; (代码52 - 4 = 38)再次&#39; 4&#39;,所以&#34; 404&#34;。

该行以/*开头评论结束,接下来两行:

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

下面的行变为空,但有点棘手,因为exit()被定义为空 AFTER 行本身。这是有效的,因为C预处理器运行 BEFORE 编译。

print(202*2);exit();

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

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

答案 2 :(得分: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,0的ASCII。打印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);  
}

答案 3 :(得分:0)

您已将V定义为putchar(),它将打印char的ascii代码并返回打印字符的ascii值。程序的执行将从主程序开始 第一个v(52)将打印4并返回52 第二个v(52-4)将打印0(48是ascii值为0)并返回48 最后它将调用v(48 + 4)将打印4,因为52是ascii值'4'。