2017-06-28 57 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'。