C-Code: Wie funktioniert das überhaupt?

Lesezeit: 3 Minuten

Benutzer-Avatar
Reverend Gonzo

Ich habe das gerade hier gesehen

#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 …

Benutzer-Avatar
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

Benutzer-Avatar
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:


objdump --disassemble /tmp/hello (edited):

080483c4 <main>:
 80483c4:       55                      push   %ebp
 80483c5:       89 e5                   mov    %esp,%ebp
 80483c7:       83 e4 f0                and    $0xfffffff0,%esp
 80483ca:       83 ec 10                sub    $0x10,%esp
 80483cd:       b8 a0 84 04 08          mov    $0x80484a0,%eax
 80483d2:       89 04 24                mov    %eax,(%esp)
 80483d5:       e8 22 ff ff ff          call   80482fc <printf@plt>
 80483da:       c9                      leave  
 80483db:       c3                      ret    
 80483dc:       90                      nop
 80483dd:       90                      nop
 80483de:       90                      nop
 80483df:       90                      nop

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:


xxd /tmp/hello | grep 00004a0

00004a0: 4865 6c6c 6f2c 2077 6f72 6c64 210a 0000  Hello, world!...

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.

1270840cookie-checkC-Code: Wie funktioniert das überhaupt?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy