2017-06-28 2 views
2

Ich habe den folgenden Code von Stack Overflow 404 Not Found Error Seite kopiert.Wie druckt dieser Code 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() 

Der obige Code kompiliert fein und druckt auf der Konsole. Ich dachte die Aussage drucken (202 * 2); ist verantwortlich für den Druck , aber ich bin nicht richtig, weil die Änderung der Zahlen in dieser Aussage auch druckt.

Könnte jemand mir helfen, diesen Code zu verstehen und wie er druckt ?

Ich poste die Kompilierungsausgabe für Ihre Referenz, da es Kommentare gibt, die besagen, dass dieser Code nicht kompiliert wird. Die Datei mit dem obigen Code ist Test.c.

gcc Test.c -o-Test

Test.c: 3: 1: Warnung: Rückgabetyp Standardwert ist 'int' [-Wimplicit-int] main() {v (4 + v (v (52) -4)); return 0;}/*^Test.c: In der Funktion 'main': Test.c: 1: 12: Warnung: implizite Deklaration der Funktion 'putchar' [-Wimplicit- function-declaration] # define v putchar ^ Test.c: 3: 8: Anmerkung: bei Expansion von Makro 'v' main() {v (4 + v (v (52) -4)); Rückgabe 0;}/* ^ Test.c: Auf oberster Ebene: Test.c: 6: 14: Warnung: Datendefinition hat keinen Typ oder Speicherklasse print (202 * 2); exit(); ^ Test.c: 6: 14: Warnung: Geben Sie standardmäßig 'int' in der Deklaration von 'exit' [-Wimplicit-int] Test.c: 6: 14: Warnung: widersprüchliche Typen für die integrierte Funktion 'exit '

./test

+2

putchar (52) Ausgänge 4; 52-4 = 48; putchar (48) gibt 0 aus; 48 + 4 = 52; putchar (52) outpus 4 erneut. –

+7

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

+0

Nur fragen: Liebe Migration zu MSO-Wähler: können Sie bitte ein wenig hinzufügen Rechtfertigung? Ich denke ich verpasse hier etwas, warum sollte migriert werden? –

Antwort

1
# define v putchar 

Dies definiert v als putchar() Funktion. Es druckt ein Zeichen und gibt es zurück.

# define print(x) 

dies definiert print(x) als nichts (so print(202*2) bedeutet nichts)

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

dies wie folgt umgeschrieben werden:

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

es ASCII-Codes '4' (Code drucken 52), '0' (Code 52 - 4 = 38) und wieder '4', also "404".

Diese Linie endet mit einem /* Kommentar beginnend die weiter durch die nächsten zwei Zeilen:

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

Die Linie unten stellt sich heraus, leer ist, aber es ist etwas schwierig, weil exit() als leere AFTER definiert ist die Linie selbst. Das funktioniert, weil der C-Präprozessor die Kompilierung BEFORE ausführt.

print(202*2);exit(); 

Die Linie unten definiert exit() als leer, oben auf der Linie eingesetzt.

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

kann keine Meta-Frage als Betrogene verwenden, so eklatant Kopieren von the MSO answer.

Da dies markiert ist und erwähnt "kompiliert", so nur die C-Teil davon extrahieren.

Danksagungen: Mark Rushakoff ist die original author of the polyglot.

Der C-Code ist ziemlich einfach zu lesen, aber auch einfacher, wenn Sie es durch einen Präprozessor laufen:

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

Ihr Standard main Funktion dort erklärt wird, und exit ist auch erklärt als Eine Funktion mit einem impliziten Rückgabetyp von int (exit wird effektiv ignoriert).

putchar wurde verwendet, weil Sie keine #include benötigen, um es zu verwenden; Sie geben es ein Integer-Argument und es setzt das entsprechende ASCII-Zeichen auf stdout und gibt den gleichen Wert zurück, den Sie ihm gegeben haben. Also, wir setzen 52 (das ist 4); dann subtrahieren wir 4 und geben 0 aus; dann fügen wir 4 zum Ausgang 4 wieder hinzu.

Auch ein wenig mehr elboration, von [Cole Johnson] (https://meta.stackoverflow.com/users/1350209/cole-johnson) answer

all das Ohne Berücksichtigung, wenn wir den Code ein bisschen neu formatiert, und ersetzen 52 mit seinem ASCII-Äquivalent ('4'), erhalten wir:

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

Was die putchar Erklärung wird durch den Standard definiert zu geben Sie den Eingang zurück, wie realloc. Zuerst druckt dieses Programm ein 4, dann den ASCII-Wert nimmt (52), subtrahiert 4 (48), Druck, die (ASCII 0), fügt 4 (52), druckt die (4), dann schließlich beendet. Daraus ergibt sich die folgende Ausgabe:

404 

Wie für dieses polyglotte gültig C++ leider sein, es ist nicht so C++ eine explizite Rückgabetyp für Funktionen erfordert. Dieses Programm nutzt die Tatsache aus, dass C Funktionen ohne einen expliziten Rückgabetyp benötigt, um int zu sein.

+2

Sollte für die Übertragung auf Meta dann stimmen. Wo kann es als dup geschlossen werden. – StoryTeller

+1

@StoryTeller Aber es ist eine gültige Frage in SO. Es geht um das Code-Verständnis, nicht um das Funktionieren von SO .... richtig? Ich verstehe, dass der Kontext sich überschneidet, aber es ist auch nicht OT hier ... Was denkst du? –

+0

Ich stimme zu, das ist ein gültiges Thema in SO ^^. Vielleicht solltest du ein Wiki beantworten. Tatsächlich ist dies die Meta-Frage, die nicht im Fokus steht. – Stargateur

1

Der Code kann auf einem Standard-C-Compiler nicht kompiliert werden, wie gcc -std=c11 -pedantic-errors.

1) main muss Int auf gehosteten Systemen zurückgeben.
2) putchar() muss #include <stdio.h> haben.
3) Sie können keine Semikolons außerhalb von Funktionen schreiben.

Nachdem diese Anfänger-Level-Fehler zu beheben und alle überflüssigen Flaum zu entfernen, die nichts tut, sondern Compiler-Fehler zu schaffen, sind wir mit dieser links:

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

Dieser dreht sich um putchar den Charakter der Rückkehr geschrieben:

putchar(4+putchar(putchar(52)-4)); 
  • 52 ist ASCII für '4'. Drucken 4.
  • 52 - 4 = 48, ASCII für 0. Drucken 0.
  • 4 + 48 = 52. Wieder 4.

drucken Und das ist es. Sehr düster, was die Verschleierungsversuche anbelangt.


Proper, standardkonforme Verschleierungs würde eher in etwa so aussehen:

#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

"Sie können keine Semikolons außerhalb von Funktionen schreiben.", Was? Du meinst Anweisungen? Übrigens sollte proto von 'main()' 'int main (void) sein; in diesem Fall sind Sie also nicht konform: p. – Stargateur

+0

@Stargateur 'print (202 * 2); exit();' wird interpretiert als '; exit();' was Unsinn ist. GCC gibt den Fehler "ISO C erlaubt nicht extra"; außerhalb einer Funktion ". Und nein, die Form von main() kann beliebige Parameter annehmen und der Standard ist nicht wirklich klar. https://stackoverflow.com/a/31263079/584518 – Lundin

0

Sie V als putchar definiert haben(), die ASCII-Code von char nehmen gedruckt werden und ascii Wert der gedruckten Rück verkohlen. Die Ausführung Ihres Programms startet von der Hauptleitung wie unten erste v (52) wird 4 drucken und zurückgeben 52 zweite v (52-4) wird 0 drucken (48 ist ASCII-Wert von 0) und zurück 48 schließlich wird es aufrufen bis v (48 + 4) wird 4 als 52 als ASCII-Wert von '4' gedruckt.