#include <stdio.h>
int main(int argc, char *argv[printf("Hello, world!\n")]) {}
Was dies tut, ist “Hello World!”
Aber was ist hier eigentlich los?
Das Beste, was ich erraten kann, ist, dass es kompiliert und an die Spitze des Ausführungsstapels geworfen wird, aber die Syntax sieht für mich nicht einmal legal aus …
Casablanca
Der Code nutzt die Array-Funktion von C99 mit variabler Länge, mit der Sie Arrays deklarieren können, deren Größe nur zur Laufzeit bekannt ist. printf gibt eine Ganzzahl zurück, die der Anzahl der tatsächlich gedruckten Zeichen entspricht, sodass der Code “Hello, world!” zuerst und verwendet den Rückgabewert als Größe von argv. Das main Die Funktion selbst macht nichts. Der eigentliche Aufruf an printf selbst geht wahrscheinlich in den vom Compiler generierten Startcode ein, der wiederum aufruft main.
Bearbeiten: Ich habe gerade die Disassemblierung des generierten Codes überprüft gcc und es scheint, dass der Anruf an printf geht hinein main selbst, vor jedem anderen Code.
Der Aufruf an printf geht definitiv nicht in irgendeiner Vor-main Startcode.
– R.. GitHub HÖR AUF, EIS ZU HELFEN
11. November 2010 um 3:33 Uhr
@R..: Das war nur eine Vermutung und das Beste, was ich machen kann. Wo sonst könnte es möglicherweise hingerichtet werden?
– Casablanca
11. November 2010 um 3:35 Uhr
@R..: Macht nichts, da hast du Recht und ich habe meine eigene Frage beantwortet. 🙂
– Casablanca
11. November 2010 um 3:40 Uhr
Ja. Konzeptionell findet dort auch der Code statt. VLA-Größenausdrücke für lokale Variablen/Funktionsargumente werden an dem Punkt berechnet, an dem die Variable definiert wird, was für Argumente der Funktionseintrag ist. Frühere Argumente (hier argc) sind zu diesem Zeitpunkt zur Verwendung verfügbar, spätere nicht.
– R.. GitHub HÖR AUF, EIS ZU HELFEN
11. November 2010 um 3:58 Uhr
jcomeau_ictx
Wenn ich herausfinde, wie der Compiler es analysiert hat, werde ich dies aktualisieren, aber zumindest muss nicht spekuliert werden, wie es kompiliert wurde:
Da ausführbare Linux-Dateien normalerweise auf 0x8048000 basieren, befindet sich die Adresse des Arguments für printf bei einem Offset von 0x00004a0 vom Beginn der Binärdatei:
Also wird die Adresse des Strings gepusht und printf wird mit diesem einen Argument aufgerufen. Nichts Magisches auf dieser Ebene, also wurden alle lustigen Sachen von gcc gemacht.
char *argv[printf("Hello, world!\n")])
printf() gibt die Anzahl der gedruckten Zeichen zurück.
So
int main(int argc, char *argv[printf("Hello, world!\n")]) {}
ist äquivalent zu
int main(int argc, char *argv[14]) {}
plus Anruf bei printf() was druckt "Hello World"
Das gilt nur, wenn es printf gelingt, alle Zeichen zu drucken.
– Welpe
11. November 2010 um 14:00 Uhr
Ich bin kein C-Experte, aber es sieht so aus, als würden die Befehlszeilenargumente gleichzeitig mit deklariert main.
12708400cookie-checkC-Code: Wie funktioniert das überhaupt?yes