Was passiert, wenn ich eine Funktion mit einer leeren Parametertabelle deklariere und Argumente an sie weitergebe?

9

Zum Beispiel

%Vor%

Ausgabe:

%Vor%

Dieser Code ist gut kompiliert (ohne Warnungen mit clang) und läuft gut. Aber ich frage mich, was passiert mit den Werten, die an foo() übergeben werden? Werden sie in den Stapel geschoben oder einfach weggeworfen?

Vielleicht klingt diese Frage nutzlos, aber es ergibt Sinn. Wenn ich zum Beispiel int main() anstelle von int main(void) habe und einige Befehlszeilenargumente an sie übergeben, wird das Verhalten von main() beeinflusst?

Wenn% ce_de% verwendet wird, ist mindestens ein benannter Parameter vor <stdarg.h> von ISO C erforderlich. Ist es möglich, dass wir solche Deklarationen als ... verwenden können, um von null zu unendlichen Argumenten an a zu übergeben Funktion?

Ich habe bemerkt, dass void foo() eine "Nicht-Prototyp-Deklaration" ist und dass void foo() gerade eine "Prototyp-Deklaration" ist. Ist das etwas relevant?

Erläuterung

Scheint, dass diese Frage als doppelt markiert ist Was bedeutet eine leere Parameterliste? [duplizieren] (Interessanterweise ist diese Frage auch doppelt ...). Tatsächlich glaube ich nicht, dass meine Frage etwas damit zu tun hat. Es konzentriert sich auf "Was void foo(void) bedeutet in C", aber ich weiß, dass bedeutet, dass "Ich kann eine beliebige Anzahl von Argumenten zu ihm übergeben", und ich weiß auch, dass es eine veraltete Funktion ist.

Aber diese Frage ist ganz anders. Das Schlüsselwort lautet "Was wäre wenn". Ich möchte nur wissen, ob ich verschiedene Mengen von Argumenten an void foo() übergebe, wie im obigen Beispielcode, können sie in void foo() verwendet werden? Wenn ja, wie wird das gemacht? Wenn nicht, machen die übergebenen Argumente einen Unterschied? Das ist meine Frage.

    
Sun Qingyao 16.02.2016, 07:25
quelle

2 Antworten

2

In% deklariert void foo() eine Funktion, die eine nicht spezifizierte Anzahl von Parametern benötigt. Eine Funktion wird folgendermaßen deklariert:

%Vor%

parameter-list ist die Liste der Parameter, die die Funktion getrennt durch Kommas benötigt. Wenn keine Parameter angegeben sind, nimmt die Funktion keine Parameter an und sollte mit einer leeren Klammer oder mit dem Schlüsselwort void definiert werden. Wenn vor einer Variablen in der Parameterliste kein Variablentyp steht, wird int angenommen.

    
zangw 16.02.2016 07:37
quelle
1

Wie Jonathan Leffler sagte, stellt die Aufrufkonvention von C fest, dass die aufrufende Funktion (nicht die aufgerufene) für das Herausspringen von Argumenten aus dem Stapel verantwortlich ist, so dass das Programm nicht abstürzt, selbst wenn die Argumente nicht mit der erwarteten Funktion übereinstimmen.

Ich füge hinzu, dass Cs Aufrufkonvention auch festlegt, dass Argumente in umgekehrter Reihenfolge auf den Stapel geschoben werden (d. h. der Aufruf foo (1, 2) schiebt die 2 dann die 1 ). Dadurch kann die aufgerufene Funktion auf die ersten Parameter zugreifen, auch wenn sie den Rest nicht kennt. Zum Beispiel kann eine Funktion, die als int foo (int a, int b, ...) deklariert wird, auf a und b zugreifen, auch wenn Sie nicht wissen, welche anderen Parameter übergeben wurden: a und b befinden sich gerade oben im Stapel. Der Zugriff auf andere Argumente würde Stack-Pointer-Hacks erfordern, was genau das ist, was printf tut. Natürlich kann man leicht lustige Ergebnisse erzielen, wenn man verschiedene Argumente von dem verwendet, was erwartet wird (zB printf ("%d%d", 3.5); ).

Also, wie pro Frage, ja, int foo () kann sicher mit einer beliebigen Anzahl / Art von Argumenten aufgerufen werden, und in den 1980er Jahren würde es als "normale Praxis" angesehen werden, Zeiger-Hacks auf dem Stapel zu verwenden, um auf unbekannte Parameter zuzugreifen . Wenn Portabilität und Lesbarkeit mehr und mehr an Bedeutung gewannen, erschien <stdarg.h> als eine portable Möglichkeit, diese Pointer-Hacks zu implementieren (der Compiler wird den richtigen Code für die Zielplattform generieren, so dass es kein "Hack" mehr ist). Wie bereits erwähnt, benötigt <stdarg.h> jedoch mindestens einen Parameter, daher kann es nicht mit int foo () helfen.

    
Jojonete 16.03.2016 14:47
quelle