Warum kein Compilerfehler für main () ohne Rückgabe am Ende?

8

Ich arbeite an einem C-Brain Teaser: Schreiben Sie das Standard-Hello-World-Programm, ohne Semikolon.

Meine beste Antwort ist bisher:

%Vor%

Aber ich verstehe nicht, warum ich keinen Compilerfehler (Visual Studio) bekomme:

%Vor%

Ich habe andere Funktionen mit einem deklarierten Rückgabetyp versucht, aber eine return-Anweisung fehlt, und bekomme diesen Compilerfehler.

Beachten Sie, dass ich es auch versucht habe:

%Vor%

Und bekomme keinen Compilerfehler auf foo. Wenn ich "exit (0)" entferne, bekomme ich den Compilerfehler. Anscheinend hat der Compiler das Wissen, dass "Exit" eine spezielle Funktion ist? Das erscheint mir sehr merkwürdig.

    
abelenky 29.01.2009, 21:10
quelle

6 Antworten

8

Wie Jens in einem Kommentar darauf hingewiesen hat, weist der gepostete Code kein undefiniertes Verhalten auf. Die ursprüngliche Antwort hier ist nicht korrekt und scheint die Frage sowieso nicht wirklich zu beantworten (wenn man alles ein paar Jahre später noch einmal liest).

Die Frage kann zusammengefasst werden als: "Warum gibt MSVC nicht die Warnung C4716 für main() unter denselben Umständen für andere Funktionen aus?"

Beachten Sie, dass Diagnose C4716 eine Warnung und kein Fehler ist. Was die C-Sprache betrifft (aus Sicht der Standards sowieso), besteht niemals die Notwendigkeit, einen Nicht-Fehler zu diagnostizieren. aber das erklärt nicht wirklich, warum es einen Unterschied gibt, es ist nur eine Technik, die bedeuten kann, dass man sich nicht zu sehr beschweren kann ...

Die wirkliche Erklärung dafür, warum MSVC die Warnung für main() nicht für andere Funktionen ausgibt, kann wirklich nur von jemandem im MSVC-Team beantwortet werden. Soweit ich das beurteilen kann, erklären die Ärzte den Unterschied nicht, aber vielleicht habe ich etwas übersehen; Also kann ich nur spekulieren:

In C ++ wird die Funktion main() speziell behandelt, da vor der schließenden Klammer ein implizites return 0; existiert.

Ich vermute, dass der C-Compiler von Microsoft die gleiche Behandlung bietet, wenn er im C-Modus kompiliert wird (wenn man sich den Assembler-Code anschaut, wird das EAX-Register gelöscht, auch wenn es keinen return 0; gibt) Es gibt keinen Grund zur Warnung C4716. Beachten Sie, dass der C-Modus von Microsoft C90-kompatibel und nicht C99-kompatibel ist. In C90 hat das Ende des Endes von main() ein undefiniertes Verhalten. Die Rückgabe von 0 erfüllt jedoch immer die niedrigen Anforderungen von undefiniertem Verhalten. Es gibt also kein Problem.

Selbst wenn das Programm in der Frage am Ende von main() lief (was zu undefiniertem Verhalten führte), gab es immer noch keine Warnung.

Original, nicht so gute Antwort:

In ANSI / ISO 90 C ist dies undefiniertes Verhalten, so dass MS wirklich einen Fehler erzeugen sollte (aber vom Standard nicht gefordert). In C99 erlaubt der Standard ein implizites return am Ende von main () - wie auch C ++.

Wenn dies also als C ++ oder C99 kompiliert wird, gibt es keinen Fehler und es ist dasselbe wie return 0; . C90 führt zu undefiniertem Verhalten (das keine Diagnose erfordert).

Interessant (na ja, vielleicht nicht), von den verschiedenen Compilern (VC9, VC6, GCC 3.4.5, Digital Mars, Comeau) habe ich das mit meinen grundlegenden, meist voreingestellten Optionen (die Umgebung, die ich immer benutze) ausprobiert Für Quick-n-Dirty-Tests von Code-Snippets ist der einzige Compiler, der vor der fehlenden return-Anweisung warnt, VC6 beim Kompilieren als C ++ - Programm (VC6 reklamiert nicht beim Kompilieren für C).

Die meisten Compiler beschweren sich (eine Warnung oder ein Fehler), wenn die Funktion nicht den Namen main hat. Digital Mars beim Kompilieren für C nicht und GCC nicht für C oder C ++.

    
Michael Burr 29.01.2009, 21:56
quelle
6

Wenn Sie nichts zurückgeben, gibt das Programm 0 zurück. Siehe Ссылка

    
ggf31416 29.01.2009 21:13
quelle
2

Die Kompilierung kann intelligent genug sein, um zu wissen, dass exit (0) aufgerufen wird, die niemals zurückkehrt, so dass sie nicht benötigt wird.

    
John Boker 29.01.2009 21:16
quelle
1

Von Ссылка

  

C ++ - Sprachreferenz

     

Beenden Sie die Funktion

     

Die Exit-Funktion, die in der   Standard-Include-Datei STDLIB.H,   beendet ein C ++ Programm.

     

Der als Argument übergebene Wert   Exit wird an den Betrieb zurückgegeben   System als Rückgabecode des Programms oder   Beendigungscode Per Konvention, eine Rückkehr   Code von Null bedeutet, dass das Programm   erfolgreich abgeschlossen.

     

Hinweis Sie können die Konstanten verwenden   EXIT_FAILURE und EXIT_SUCCESS, definiert   in STDLIB.H, um den Erfolg anzuzeigen oder   Ausfall Ihres Programms.

     

Ausstellen a   Rückgabebestätigung von der Hauptleitung   Funktion entspricht dem Aufruf der   Exit-Funktion mit dem Rückgabewert als   sein Argument.

John MacIntyre 29.01.2009 21:36
quelle
1

Weil es kein Fehler ist - es ist ein undefiniertes Verhalten. Siehe Abschnitt 6.9.1, Absatz 12 des C99-Standards:

  

Wenn das}, das eine Funktion beendet, erreicht ist und der Wert des Funktionsaufrufs vom Aufrufer verwendet wird, ist das Verhalten nicht definiert.

Somit kann der Compiler tun, was er will, wenn er sieht, dass der Code nicht zurückkommt - er kann einen Fehler, eine Warnung oder gar nichts ausgeben. Im Fall von GCC kompiliert es standardmäßig erfolgreich ohne Warnungen oder Fehler. Mit der Option -Wall wird eine Warnung ausgegeben.

main() ist speziell in C: es ist die einzige Funktion, die keinen Wert zurückgeben darf. Der C-Standard besagt, dass, wenn die Steuerung das Ende von main() ohne return -Anweisung erreicht, implizit 0 zurückgibt. Dies gilt nur für main() , alle anderen nicht-void-Funktionen müssen einen Wert zurückgeben.

Abschnitt 5.1.2.2.3:

  

Wenn der Rückgabetyp der Hauptfunktion ein Typ ist, der mit int kompatibel ist, wird eine Rückkehr von der   Der erste Aufruf der Hauptfunktion entspricht dem Aufruf der Exit-Funktion mit dem Wert, der von der Hauptfunktion zurückgegeben wird, als ihr Argument, 10) das Erreichen der}, die das beendet   Die main-Funktion gibt den Wert 0 zurück. Wenn der Rückgabetyp nicht mit int kompatibel ist, wird der Wert zurückgegeben   Der Beendigungsstatus, der an die Host-Umgebung zurückgegeben wird, ist nicht angegeben.

    
Adam Rosenfield 29.01.2009 21:24
quelle
0

Wenn wir nicht von main zurückkommen, oder genauer gesagt, das abschließende '}' der Hauptfunktion nicht erreichen, ist das aus verschiedenen Gründen völlig in Ordnung. Typische Fälle sind Schleifen für immer und Beenden oder Abbrechen vor.

In diesem Fall wird garantiert, dass exit(0) ausgeführt wird, bevor das Ende von main erreicht wird. Warum sollte der Compiler warnen? Sie würden keine Warnung für diese erwarten, oder?

%Vor%

Ich wäre sogar überrascht, wenn

%Vor%

würde nicht warning: unreachable code: return 0 oder sowas verursachen.

    
Jens 12.05.2012 16:30
quelle

Tags und Links