396 Stimmen

Warum lässt sich eine Funktion ohne Parameter (im Vergleich zur eigentlichen Funktionsdefinition) kompilieren?

Ich bin gerade auf einen C-Code von jemandem gestoßen, bei dem ich mich frage, warum er kompiliert wird. Es gibt zwei Punkte, die ich nicht verstehe.

  1. En Funktionsprototyp hat im Vergleich zur eigentlichen Funktionsdefinition keine Parameter.

  2. Der Parameter in der Datei Funktionsdefinition hat keinen Typ.


#include <stdio.h>

int func();

int func(param)
{
    return param;
}

int main()
{
    int bla = func(10);    
    printf("%d", bla);
}

Warum funktioniert das? Ich habe es in mehreren Compilern getestet, und es funktioniert gut.

275voto

Krishnabhadra Punkte 33954

Alle anderen Antworten sind richtig, aber nur für Fertigstellung

Eine Funktion wird auf die folgende Weise deklariert:

  return-type function-name(parameter-list,...) { body... }

Rückgabeart ist der Variablentyp, den die Funktion zurückgibt. Dies kann kein Array-Typ oder ein Funktionstyp sein. Wenn nicht angegeben, dann int angenommen .

Funktionsname ist der Name der Funktion.

Parameter-Liste ist die Liste der Parameter, die die Funktion benötigt, getrennt durch Kommas. Wenn keine Parameter angegeben werden, wird die Funktion keine Parameter und sollte mit einem leeren Satz von Klammern oder mit dem Schlüsselwort void definiert werden. Steht kein Variablentyp vor vor einer Variablen in der Parameterliste steht, wird int angenommen . Arrays und Funktionen werden nicht an Funktionen übergeben, sondern automatisch in zu Zeigern konvertiert. Wenn die Liste mit einem Auslassungszeichen (,...) abgeschlossen wird, dann gibt es keine festgelegte Anzahl von Parametern. Hinweis: Der Header stdarg.h kann verwendet werden, um auf Argumente zuzugreifen, wenn ein Auslassungszeichen verwendet wird.

Und nochmals der Vollständigkeit halber. Aus C11 Spezifikation 6:11:6 (Seite: 179)

En Verwendung von Funktionsdeklaratoren mit leeren Klammern ( Deklaratoren für Parameter im Prototyp-Format) i Funktion .

161voto

Tony The Lion Punkte 59566

In C func() bedeutet, dass Sie eine beliebige Anzahl von Argumenten übergeben können. Wenn Sie keine Argumente wollen, müssen Sie als func(void) . Der Typ, den Sie Ihrer Funktion übergeben, ist, falls nicht angegeben, standardmäßig int .

61voto

Jens Punkte 65511

int func(); ist eine veraltete Funktionsdeklaration aus der Zeit, als es noch keinen C-Standard gab, d. h. aus der Zeit von K&R C (vor 1989, dem Jahr, in dem die erste "ANSI C"-Norm veröffentlicht wurde).

Denken Sie daran, dass es keine Prototypen in K&R C und das Schlüsselwort void war noch nicht erfunden. Alles, was man tun konnte, war, dem Compiler die Rückgabetyp einer Funktion. Die leere Parameterliste in K&R C bedeutet "eine nicht spezifizierte, aber feste" Anzahl von Argumenten. Fest bedeutet, dass Sie die Funktion mit der Option dieselbe Anzahl von Argumenten jedes Mal (im Gegensatz zu einer variadisch Funktion wie printf wobei die Anzahl und Art der Anrufe variieren kann).

Viele Compiler diagnostizieren dieses Konstrukt; insbesondere gcc -Wstrict-prototypes wird Ihnen sagen: "Funktionsdeklaration ist kein Prototyp", was genau richtig ist, weil es siehe wie ein Prototyp (besonders wenn man von C++ vergiftet ist!), ist es aber nicht. Es handelt sich um eine K&R C-Rückgabewert-Deklaration im alten Stil.

Faustformel: Lassen Sie niemals eine leere Parameterlistendeklaration leer, verwenden Sie int func(void) um genau zu sein. Dadurch wird die K&R-Rückgabedeklaration zu einem richtigen C89-Prototyp. Die Compiler sind glücklich, die Entwickler sind glücklich, die statischen Prüfer sind glücklich. Diejenigen, die von^W^Wfond of C++ in die Irre geführt werden, könnten allerdings zusammenzucken, weil sie zusätzliche Zeichen eingeben müssen, wenn sie versuchen, ihre Fremdsprachenkenntnisse anzuwenden :-)

53voto

unwind Punkte 377331
  • Die leere Parameterliste bedeutet "beliebige Argumente", so dass die Definition nicht falsch ist.
  • Es wird angenommen, dass der fehlende Typ int .

Ich würde jeden Build, der dies passiert, als unzureichend konfigurierte Warnung/Fehlerebene betrachten, obwohl es keinen Sinn macht, dies für tatsächlichen Code zu erlauben.

30voto

Lei Mou Punkte 2462

Es ist K&R Stil Funktionsdeklaration und -definition. Aus der C99-Norm (ISO/IEC 9899:TC3)

Abschnitt 6.7.5.3 Funktionsdeklaratoren (einschließlich Prototypen)

Eine Bezeichnerliste deklariert nur die Bezeichner der Parameter der Funktion. Eine leere Liste in einem Funktionsdeklarator, der Teil einer Definition dieser Funktion ist, gibt an, dass die Funktion keine Parameter hat. Die leere Liste in einem Funktionsdeklarator, der nicht Teil einer Definition dieser Funktion ist, gibt an, dass keine Informationen über die Anzahl oder den Typ der Parameter geliefert wird. (Wenn beide Funktionstypen "old style" sind, werden die Parametertypen nicht verglichen).

Abschnitt 6.11.6 Funktionsdeklaratoren

Die Verwendung von Funktionsdeklaratoren mit leeren Klammern (keine Parameter im Prototyp-Format Typdeklaratoren) ist ein ein veraltetes Merkmal.

Abschnitt 6.11.7 Funktionsdefinitionen

Die Verwendung von Funktionsdefinitionen mit separaten Parameterbezeichnern und Deklarationslisten (nicht Prototyp-formatige Parametertyp- und Bezeichnerdeklaratoren) ist eine ein veraltetes Merkmal.

Was der alte Stil bedeutet K&R Stil

Beispiel:

Erklärung: int old_style();

Definition:

int old_style(a, b)
    int a; 
    int b;
{
     /* something to do */
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X