我从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 回答
这将
v
定义为putchar()
函数 . 它打印一个字符并返回它 .这将
print(x)
定义为什么(所以print(202*2)
表示什么都没有)这可以改写为:
它使用ASCII码打印'4'(代码52),'0'(代码52-4 = 38)并再次打印'4',所以“404” .
该行以
/*
开头,继续通过接下来的两行注释:下面的行变为空,但它有点棘手,因为
exit()
在行本身后被定义为空 . 这是因为C预处理器在编译之前运行 .下面的行将
exit()
定义为空,在上面的行中使用 .不能使用元问题作为欺骗,所以公然复制MSO的答案 .
由于这被标记为c并且提到了"compiled",所以只提取它的C部分 .
Credits: Mark Rushakoff is the original author of the polyglot.
此外,从[Cole Johnson's](https://meta.stackoverflow.com/users/1350209/cole-johnson)answer获得更多的合作
代码无法在标准C编译器上编译,例如
gcc -std=c11 -pedantic-errors
.1)main必须在托管系统上返回int .
2)putchar()必须有
#include <stdio.h>
.3)你不能在函数外写分号 .
修复这些初学者级别的错误并删除除了创建编译器错误之外没有做任何事情的所有多余的绒毛,我们留下这个:
这围绕着putchar返回写的字符:
52是
'4'
的ASCII . 打印4 .52 - 4 = 48,ASCII为
0
. 打印0 .4 48 = 52.再次打印4 .
就是这样 . 混淆尝试非常暗淡 .
正确的,符合标准的混淆看起来应该是这样的:
你已经将V定义为putchar(),其中打印了要打印的字符的ascii代码并返回打印字符的ascii值 . 执行程序将从主程序开始,如下图所示v(52)将打印4和返回52秒v(52-4)将打印0(48是ascii值为0)并返回48最后它将调用v(48 4)将打印4,因为52是ascii值'4' .