Was war der Grund dafür, „return 0“ am Ende von „main“ optional zu machen?

Lesezeit: 6 Minuten

Edwards Benutzeravatar
Eduard

Beginnend mit dem C99-Standard muss der Compiler das Äquivalent von a generieren return 0 oder return EXIT_SUCCESS wenn nein Rückkehr wird am Ende geliefert main. Etwa zur gleichen Zeit gab es auch eine entsprechende und identische Änderung am C++-Sprachstandard. Ich interessiere mich für die Gründe für beide und ich schätzte, dass es unwahrscheinlich war, dass es sich um völlig getrennte und nicht zusammenhängende Änderungen handelte.

Meine Frage ist:

Was war die dokumentierte Begründung für diese Änderung?

Eine ideale Antwort würde maßgebliche Quellen für C und C++ zitieren, weshalb ich die Frage mit beiden Sprachen markiert habe.

Beachten Sie, dass ich im Gegensatz zu der Frage Was die Gründe für/gegen die Rückgabe von 0 von main in ISO C++? nicht um Rat frage, ob ich schreiben soll return 0 in meinen Programmen — ich frage, warum die Sprachstandards selbst geändert wurden.


Um den Zweck der Frage zu verstehen, hier ein bisschen mehr Kontext:

  1. Zu verstehen, warum eine Änderung vorgenommen wurde, ist hilfreich bei der Entscheidung, wie sie verwendet werden soll.
  2. Die Begründung ist häufig in der Norm selbst enthalten. Zum Beispiel enthält der C90-Standard viele erläuternde Fußnoten, wie Fußnote 36, die mit „Die Absicht dieser Liste …“ beginnt.

Ich habe die Standards studiert und selbst nach der Antwort gesucht, bevor ich hier gefragt habe, aber keine Antwort gefunden. Ich wurde gebeten, beim Schreiben von Codierungsstandards für beide Sprachen für eine Gruppe von Programmierern zu helfen, und ich wollte sicherstellen, dass ich verstehe, warum diese Funktion existiert, damit ich anderen ihre Verwendung genau erklären kann.

  • @Olaf: Sprachänderungsvorschläge werden normalerweise mit den Gründen für die vorgeschlagene Änderung dokumentiert. Ich bitte um diese Dokumentation, nicht für Spekulationen.

    – Eduard

    13. Juli 2015 um 22:07 Uhr

  • C++98 ging C99 voraus, also liegt die Antwort wahrscheinlich in WG21, nicht in WG14 … möglicherweise sogar in Vorstandard-C++, hat jemand das alte Buch?

    – o11c

    13. Juli 2015 um 22:23 Uhr


  • Dies müssen zwei Fragen sein, eine für C, eine für C++. Fühlen Sie sich frei, Links in jede Frage zur anderen einzufügen.

    – Ben Voigt

    13. Juli 2015 um 22:42 Uhr

  • Das Vorwort zum C99-Standard enthält eine Liste der “wichtigsten Änderungen” gegenüber der vorherigen Ausgabe. Die Änderung, die das Ende des Herunterfallens bewirkte main gleichwertig return 0; wird nicht erwähnt, und der Abschnitt, in dem die Änderung vorgenommen wurde (5.1.2.2.3), bietet keine Begründung.

    – Keith Thompson

    13. Juli 2015 um 23:03 Uhr


  • @Olaf das ist weder spekulativ noch meinungsbasiert. Änderungen an C und C++ werden als Teil des Standardprozesses vorgenommen und alle Änderungen haben eine Begründung. Es kann schwierig sein, ein öffentliches Dokument für einen bestimmten Fall zu finden, aber es gibt eine Begründung und es ist eine berechtigte Frage.

    – Shafik Yaghmour

    14. Juli 2015 um 4:01 Uhr

Benutzeravatar von Shafik Yaghmour
Shafik Yaghmur

Im Der neue C-Standard Sektion 5.1.2.2.3 Programmbeendigung der Autor Derek Jones Kommentar zu diesen Zeilen aus dem C99-Standard:

Das Erreichen von }, das die Hauptfunktion beendet, gibt den Wert 0 zurück

ist:

Der Standard muss sich endlich schlampigen bestehenden Praktiken beugen.

Was darauf hinweist, dass der Grund darin bestand, schlechte Programmierpraktiken in Bezug auf die explizite Rückgabe eines Werts von anzugehen main. Zuvor war der zurückgegebene Status undefiniert.

Er weist darauf hin, dass viele Implementierungen dies bereits in C90 implementiert haben, sodass die Tatsache, dass diese Änderung bereits die gemeinsame Implementierung widerspiegelte, wahrscheinlich auch geholfen hat.

  • C89 bereits erforderlich “Wenn die Hauptfunktion eine Rückgabe ausführt, die keinen Wert angibt, ist der an die Hostumgebung zurückgegebene Beendigungsstatus undefiniert.” Es war also (zumindest) kein undefiniertes Verhalten, und es gibt keinen Unterschied zwischen C89 und C99, wenn die Hostumgebung den Exit-Wert nicht verwendet.

    – Kartoffelklatsche

    14. Juli 2015 um 3:24 Uhr

Das offizielles Begründungsdokument für C99 geht darauf kaum ein. Anscheinend exit(0) wurde der Standard für den Kontrollfluss am Ende der Hauptleitung, weil exit(0) wurde eine aussagekräftige portable Semantik gegeben.

Hier sind die beiden relevanten Abschnitte:

5.1.2.2.1 Programmstart

Das Verhalten der Argumente zu mainund der Interaktion von exit, main und atexit (siehe §7.20.4.2) wurde kodifiziert, um unerwünschte Vielfalt in der Darstellung einzudämmen argv Zeichenfolgen und im Sinne von Werten, die von zurückgegeben werden main.

Die Angabe von argc und argv Als Argumente erkennt man vor allem umfangreiche Vorpraktiken an.

argv[argc] muss ein Nullzeiger sein, um eine redundante Prüfung für das Ende der Liste bereitzustellen, ebenfalls auf der Grundlage allgemeiner Praxis.

main ist die einzige Funktion, die portabel mit null oder zwei Argumenten deklariert werden kann. (Die Anzahl der Argumente anderer Funktionen muss zwischen Aufruf und Definition genau übereinstimmen.) Dieser Sonderfall erkennt einfach die weit verbreitete Praxis an, die Argumente bis wegzulassen main wenn das Programm nicht auf die Programmargumentzeichenfolgen zugreift. Während viele Implementierungen mehr als zwei Argumente unterstützen main, eine solche Praxis wird vom Standard weder gesegnet noch verboten; ein Programm, das main mit drei Argumenten definiert, ist nicht strikt konform (siehe §J.5.1.).

Die Befehlszeilen-E/A-Umleitung wird vom Standard nicht vorgeschrieben, da dies als Funktion des zugrunde liegenden Betriebssystems und nicht der Sprache C angesehen wurde.

und

7.20.4.3 Die Ausgangsfunktion

Das Argument zu exit ist eine Statusanzeige, die an die aufrufende Umgebung zurückgegeben wird. Im UNIX-Betriebssystem ist ein Wert von Null der erfolgreiche Rückkehrcode von einem Programm. Da sich die Verwendung von C über UNIX hinaus ausgebreitet hat, exit(0) wurde oft als Redewendung beibehalten, die auf eine erfolgreiche Beendigung hinweist, auch auf Betriebssystemen mit unterschiedlichen Rückgabecodesystemen. Diese Verwendung wird somit als Standard anerkannt. Seit den Argumenten to exit sind implementierungsdefiniert. Das EXIT_FAILURE Makro wurde zu C89 hinzugefügt, um eine solche Fähigkeit bereitzustellen. EXIT_SUCCESS wurde ebenfalls hinzugefügt.

Abgesehen von Anrufen, die explizit von einem Programmierer codiert wurden, exit wird bei der Rückkehr von aufgerufen main. Somit ist zumindest in diesem Fall der Körper von exit kann nicht von der Existenz anderer Objekte mit automatischer Aufbewahrungsdauer als den in deklarierten ausgehen exit.

Der Ausschuss prüfte die Hinzufügung von _exit, lehnte es jedoch aufgrund von Bedenken hinsichtlich der Unvereinbarkeit mit der POSIX-Spezifikation ab, auf der es basiert. Eine geäußerte Sorge ist zum Beispiel die _exit wurde als Möglichkeit angegeben, aus einem Signal-Handler herauszukommen, ohne ein weiteres Signal auszulösen, aber das ist eigentlich nicht der Weg _exit verhält sich in POSIX-Umgebungen. Solche falschen Hoffnungen wollte das Komitee den Programmierern nicht machen. (Aber siehe §7.20.4.4 für C99.)

  • “Anscheinend exit(0) wurde der Standard für den Kontrollfluss am Ende der Hauptleitung, weil exit(0) wurde eine aussagekräftige portable Semantik gegeben.” — Das folgt nicht ganz. C89/C90 spezifiziert das exit(0) (oder return 0; aus main) bezeichnet eine erfolgreiche Beendigung, aber ein Abfallen des Endes von main wurde nicht gleichwertig gemacht return 0; bis C99.

    – Keith Thompson

    13. Juli 2015 um 22:51 Uhr

  • Ich schätze die Mühe. Es scheint die Motivation zwischen der Äquivalenz von zu erklären return 0 und return EXIT_SUCCESS aber nicht die weitere Mutation ohne Wiederkehr, die als interpretiert wird return 0. Wenn Sie es dort sehen, können Sie erklären, wo Sie es sehen?

    – Eduard

    14. Juli 2015 um 2:12 Uhr

  • Beachten Sie das Finishing main() mit exit(0); unterscheidet sich von beidem return 0; oder einfach am Ende herunterfallen (obwohl die Unterschiede in der Praxis selten eine Rolle spielen). Insbesondere, wenn Sie anrufen exit(0);lokale Variablen in main() existieren noch, während sie mit a aus dem Geltungsbereich herausfallen return (implizit oder explizit). Einmal könnte dies eine Rolle spielen, wenn Sie unvorsichtig waren und eine lokale Variable als Puffer für einen Dateistream verwendet haben – setbuf() oder setvbuf() — und die Datei muss durch den Bereinigungscode geschlossen werden. Sie müssen versuchen, den Unterschied zu übersehen, aber er ist da.

    – Jonathan Leffler

    24. Februar 2017 um 21:29 Uhr

1390850cookie-checkWas war der Grund dafür, „return 0“ am Ende von „main“ optional zu machen?

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

Privacy policy