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.

15voto

Shiplu Mokaddim Punkte 54255

C nimmt an int wenn bei der Rückgabe der Funktion und der Parameterliste kein Typ angegeben ist . Nur bei dieser Regel sind folgende seltsame Dinge möglich.

Eine Funktionsdefinition sieht wie folgt aus.

int func(int param) { /* body */}

Wenn es ein Prototyp ist, schreiben Sie

int func(int param);

Im Prototyp können Sie nur den Typ der Parameter angeben. Der Name des Parameters ist nicht obligatorisch. Also

int func(int);

Auch wenn Sie den Parametertyp nicht angeben, sondern den Namen int wird als Typ angenommen.

int func(param);

Wenn Sie weiter gehen, funktioniert auch das Folgen.

func();

Der Compiler geht davon aus int func() wenn Sie schreiben func() . Aber setzen Sie nicht func() innerhalb eines Funktionskörpers. Das wird ein Funktionsaufruf sein

11voto

RTOSkit Punkte 1181

Wie @Krishnabhadra schon sagte, sind alle bisherigen Antworten anderer Nutzer richtig interpretiert worden, und ich möchte nur einige Punkte genauer analysieren.

Im Old-C wie auch im ANSI-C wird das " untypisierter formaler Parameter ", nehmen Sie die dimencion Ihrer Arbeit Register oder Anweisung Tiefe Fähigkeit (Schatten-Register oder Anweisung kumulativen Zyklus), in einem 8bit MPU, wird ein int16, in einem 16bit MPU und so wird ein int16 und so weiter, im Falle 64bit Architekturen können wählen, um Optionen wie kompilieren: -m32.

Auch wenn die Umsetzung auf hoher Ebene einfacher zu sein scheint, Bei der Übergabe von mehreren Parametern wird die Arbeit des Programmierers in der Kontrolldimencion Datentyp Schritt, anspruchsvoller.

In anderen Fällen, für einige Mikroprozessor-Architekturen, die ANSI-Compiler angepasst, nutzte einige dieser alten Funktionen, um die Verwendung des Codes zu optimieren, zwingt den Ort dieser "untyped formalen Parameter" zu arbeiten innerhalb oder außerhalb der Arbeit Register, heute erhalten Sie fast das gleiche mit der Verwendung von "volatile" und "Register".

Es ist jedoch anzumerken, dass die meisten modernen Compiler, keinen Unterschied zwischen den beiden Arten der Parameterdeklaration machen.

Beispiele für eine Kompilierung mit gcc unter Linux:

main.c

main2.c

main3.c  
In jedem Fall ist die Angabe des Prototyps vor Ort sinnlos, da es keinen Aufruf ohne Parameter gibt, der auf diesen Prototyp verweist. Wenn Sie das System mit "untypisierten Formalparametern" für einen externen Aufruf verwenden, fahren Sie fort, einen deklarativen Prototyp-Datentyp zu erzeugen.

Zum Beispiel so:

int myfunc(int param);

5voto

none Punkte 11623

Was den Parametertyp betrifft, so gibt es hier bereits richtige Antworten, aber wenn Sie es vom Compiler hören wollen, können Sie versuchen, einige Flags hinzuzufügen (Flags sind sowieso fast immer eine gute Idee).

Kompilieren Ihres Programms mit gcc foo.c -Wextra Ich verstehe:

foo.c: In function ‘func’:
foo.c:5:5: warning: type of ‘param’ defaults to ‘int’ [-Wmissing-parameter-type]

Seltsamerweise -Wextra fängt dies nicht für clang (es erkennt nicht -Wmissing-parameter-type aus irgendeinem Grund, vielleicht aus den oben erwähnten historischen Gründen), aber -pedantic tut:

foo.c:5:10: warning: parameter 'param' was not declared, 
defaulting to type 'int' [-pedantic]
int func(param)
         ^
1 warning generated.

Und zum Thema Prototypen, wie oben schon gesagt int func() bezieht sich auf beliebige Parameter, es sei denn, Sie definieren es explizit als int func(void) was dann erwartungsgemäß zu Fehlern führen würde:

foo.c: In function ‘func’:
foo.c:6:1: error: number of arguments doesn’t match prototype
foo.c:3:5: error: prototype declaration
foo.c: In function ‘main’:
foo.c:12:5: error: too many arguments to function ‘func’
foo.c:5:5: note: declared here

oder in clang als:

foo.c:5:5: error: conflicting types for 'func'
int func(param)
    ^
foo.c:3:5: note: previous declaration is here
int func(void);
    ^
foo.c:12:20: error: too many arguments to function call, expected 0, have 1
    int bla = func(10);
              ~~~~ ^~
foo.c:3:1: note: 'func' declared here
int func(void);
^
2 errors generated.

3voto

P.P Punkte 111806

Wenn die Funktionsdeklaration keine Parameter hat, d.h. leer ist, nimmt sie eine unbestimmte Anzahl von Argumenten an. Wenn Sie wollen, dass sie keine Argumente annimmt, ändern Sie sie in:

int func(void);

0voto

Ed Schouten Punkte 490

Deshalb rate ich den Leuten normalerweise, ihren Code mit zu kompilieren:

cc -Wmissing-variable-declarations -Wstrict-variable-declarations -Wold-style-definition

Diese Flaggen erzwingen eine Reihe von Dingen:

  • -Variablen-Erklärungen: Es ist nicht möglich, eine nicht-statische Funktion zu deklarieren, ohne zuerst einen Prototyp zu erhalten. Dies macht es wahrscheinlicher, dass ein Prototyp in einer Header-Datei mit der tatsächlichen Definition übereinstimmt. Alternativ dazu wird erzwungen, dass Sie das Schlüsselwort static zu Funktionen hinzufügen, die nicht öffentlich sichtbar sein müssen.
  • -Strich-Variablen-Erklärungen: Der Prototyp muss die Argumente korrekt auflisten.
  • -Wald-Stil-Definition: Die Funktionsdefinition selbst muss auch die Argumente korrekt auflisten.

Diese Flags werden auch in vielen Open-Source-Projekten standardmäßig verwendet. Zum Beispiel hat FreeBSD diese Flags aktiviert, wenn Sie mit WARNS=6 in Ihrem Makefile bauen.

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