2017-06-28 56 views
2

我从以下代码复制了Stack Overflow的404 Not Found Error页面这段代码如何打印404?

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

上面的代码编译好,并打印在控制台上。我认为陈述print(202 * 2);负责印刷,但我不是正确的,因为更改此声明中的数字还打印。

有人能帮我理解这段代码,它是如何打印的?

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

GCC TEST.C -o测试

TEST.C:3:1:警告:返回类型默认为 'INT'[-Wimplicit-INT] 主(){V(4 + V (v(52)-4)); return 0;}/* Test.c:在函数'main'中: Test.c:1:12:warning:隐式声明函数'putchar' [-Wimplicit-函数声明] #define v putchar ^ Test.c:3:8:note:in macro'v'main(){v(4 + v(v(52)-4)); return 0;}/* ^ Test.c:顶层:Test.c:6:14:警告:数据定义没有类型或存储类型print(202 * 2); exit(); ^ Test.c:6:14:warning:在'exit'声明中默认为'int'[-Wimplicit-int] Test.c:6:14:警告: 内置函数'exit'的冲突类型“

./Test

+2

putchar(52)输出4; 52-4 = 48; putchar(48)输出0; 48 + 4 = 52; putchar(52)outpus 4再次。 –

+7

https://meta.stackoverflow.com/questions/252184/whats-the-joke-in-the-stack-overflow-404-page-code – rsp

+0

就问:亲爱的迁移到MSO选民:可以请你加点理由?我想我在这里错过了为什么应该迁移? –

回答

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()被定义为空AFTER线路本身。这是有效的,因为C预处理器在运行之前编译了

print(202*2);exit(); 

下面一行定义为exit()为空,用于上面的行。

#define/*>[email protected]*/exit() 
1

无法从the MSO answer使用的元问题的重复数据删除,这样公然复制。

由于这是标记并提到“编译”,所以只是提取它的C部分。

Credits: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

此外,多了几分elboration,从[科尔约翰逊] (https://meta.stackoverflow.com/users/1350209/cole-johnsonanswer

不顾一切,当我们重新格式化代码位,并用其ASCII等效替换 52'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

+2

应投票转移到元然后。它可以作为一个副本关闭。 – StoryTeller

+1

@StoryTeller但它是__在SO中的一个有效问题。这是关于代码的理解,而不是关于SO的工作......对吧?我知道背景是重叠的,但这不是OT,无论你是怎么想的? –

+0

我同意这是SO ^^中的一个有效主题。也许做一个维基答案。事实上,这是一个偏离主题的元问题。 – Stargateur

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

“你不能在函数外面写分号”,什么?你的意思是说明?顺便说一句,'main()'的原型应该是'int main(void);'在这种情况下,所以你不符合:p。 – Stargateur

+0

@ Stargateur'print(202 * 2); exit();'被解释为'; exit();'这是无稽之谈。 GCC提供错误“ISO C不允许额外”;“在功能之外“。不,main()的形式可以采用任何参数,标准也不是很清楚。 https://stackoverflow.com/a/31263079/584518 – Lundin

0

您已经定义V作为的putchar(),这需要焦炭的ASCII码要打印并返回打印的ASCII值焦炭。程序的执行会从主作为波纹管 第一个V(52)开始将打印4和返回52 第二V(52-4)将打印0(48是0 ASCII值),并返回48 最终它将调用到v(48 + 4)将打印4为52是ascii值'4'。