Eigentlich gibt es einen Unterschied, aber er ist subtil. Es hat mehr Auswirkungen auf C ++, aber die Unterschiede sind wichtig.
Wenn ich rufe return
in main()
wird Destruktoren für meine lokal scoped Objekte aufgerufen werden. Wenn ich anrufeexit()
, wird kein Destruktor für meine Objekte mit lokalem Gültigkeitsbereich aufgerufen! Lesen Sie das noch einmal. exit()
kommt nicht zurück . Das heißt, wenn ich es einmal nenne, gibt es "keine Backsies". Alle Objekte, die Sie in dieser Funktion erstellt haben, werden nicht zerstört. Oft hat dies keine Auswirkungen, aber manchmal auch das Schließen von Dateien (möchten Sie sicher, dass alle Ihre Daten auf die Festplatte übertragen werden?).
Beachten Sie, dass static
Objekte auch dann aufgeräumt werden, wenn Sie anrufen exit()
. Beachten Sie schließlich, dass bei Verwendung abort()
keine Objekte zerstört werden. Das heißt, keine globalen Objekte, keine statischen Objekte und keine lokalen Objekte werden ihre Destruktoren aufgerufen.
Gehen Sie vorsichtig vor, wenn Sie die Ausfahrt der Rückkehr vorziehen.
http://groups.google.com/group/gnu.gcc.help/msg/8348c50030cfd15a
thread_local
die Destruktoren von Objekten aufgerufen werden. Destruktoren für andere lokale Objekte werden immer noch nicht aufgerufen. ideone.com/Y6Dh3fexit()
sauberen Schließens von Dateien tatsächlich falsch. Die einzige Zeit, in der Daten möglicherweise nicht gelöscht werden, ist im umgekehrten Fall: dh wenn manreturn
from verwendetmain()
und aufgerufen hatsetbuf()
oder wennsetvbuf()
ein Puffer als automatische Speicherung in deklariert istmain()
(wie in der Antwort von R. unten erläutert). Es ist wirklich schade, dass diese Frage sowohl mit C als auch mit C ++ gekennzeichnet ist (und mit Codierungsstil - es ist kein Stilproblem!).Ein weiterer Unterschied: Es
exit
handelt sich um eine Standardbibliotheksfunktion, sodass Sie Header einfügen und mit der Standardbibliothek verknüpfen müssen. Zur Veranschaulichung (in C ++) ist dies ein gültiges Programm:Für die Verwendung
exit
benötigen Sie jedoch ein Include:Dies fügt eine zusätzliche Annahme hinzu: Das Anrufen
exit
vonmain
hat die gleichen Nebenwirkungen wie das Zurückgeben von Null. Wie andere bereits betont haben, hängt dies davon ab, welche Art von ausführbarer Datei Sie erstellen (dh wer anruftmain
). Codieren Sie eine App, die die C-Laufzeit verwendet? Ein Maya-Plugin? Ein Windows-Dienst? Ein Fahrer? Jeder Fall erfordert Nachforschungen, um festzustellen, ob diesexit
gleichwertig istreturn
. IMHO zu verwenden,exit
wenn Sie wirklich meinen,return
macht den Code nur verwirrender. OTOH, wenn du es wirklich meinstexit
, dann benutze es auf jeden Fall.quelle
Es gibt mindestens einen Grund, den Sie bevorzugen sollten
exit
: Wenn einer Ihreratexit
Handler auf Daten zur automatischen Speicherdauer in verweistmain
oder wenn Sie einen Puffer mit automatischer Speicherdauer in einem der Standard-Streams verwendetsetvbuf
oder diesemsetbuf
zugewiesen habenmain
, kehren Sie von denmain
Erzeugnissen zurück undefiniertes Verhalten, aber Aufrufexit
ist gültig.Eine andere mögliche Verwendung (normalerweise jedoch für Spielzeugprogramme reserviert) besteht darin, ein Programm mit rekursiven Aufrufen von zu verlassen
main
.quelle
main()
- es ist nur eine Funktion wie jede andere. Auf der anderen Seite muss der Standard, da er in der Norm besonders erwähnt wird, ziemlich vorsichtig sein, wie er definiertmain()
und was ihm nahe und teuer ist. Letztendlich verlangt der Standard jedoch nicht (und darf auch nicht ), dass Compiler etwas Besonderes in Bezug auf die automatische Speicherung in tunmain()
. Bitte lesen Sie die Fußnote 11 unter dem Absatz, auf den Sie in Ihrem Kommentar verwiesen haben.Ich benutze immer,
return
weil der Standardprototyp fürmain()
sagt, dass er ein zurückgibtint
.Einige Versionen der Standards bieten jedoch eine
main
Sonderbehandlung und gehen davon aus, dass sie 0 zurückgeben, wenn keine explizitereturn
Aussage vorliegt. Gegeben den folgenden Code:G ++ generiert nur eine Warnung für
foo()
und ignoriert die fehlende Rückgabe vonmain
:quelle
return
, um ihre Ausführung zu beenden. Das Aufrufenexit()
ist auch eine gültige und manchmal notwendige Möglichkeit, die Ausführung einer Funktion zu beenden. Wie ich und andere an anderer Stelle beschrieben haben, vermittelt das Aufrufen vonexit()
sogarmain()
eine weitaus klarere Absicht, den gesamten Prozess zu beenden, die automatische Speicherung bis zum Beenden des Prozesses beizubehalten und die Wartung während des zukünftigen Refactorings von Code zu vereinfachen. Für C ist es daher wohl eine schlechte Praxis ,return
in zu verwenden,main()
wenn die Absicht besteht, den Prozess zu beenden.Ich stimme dem Kommentar von R. zur Verwendung von exit () mit Nachdruck zu, um zu vermeiden, dass der automatische Speicher
main()
zurückgefordert wird, bevor das Programm tatsächlich endet. Einereturn X;
Anweisung inmain()
ist nicht genau gleichbedeutend mit einem Aufruf vonexit(X);
, da die dynamische Speicherung vonmain()
verschwindet, wennmain()
sie zurückgegeben wird. Sie verschwindet jedoch nicht, wennexit()
stattdessen ein Aufruf von erfolgt.Darüber hinaus weist eine
return
Anweisung in C oder einer C-ähnlichen Sprache den Leser stark darauf hin, dass die Ausführung in der aufrufenden Funktion fortgesetzt wird, und während diese Fortsetzung der Ausführung normalerweise technisch wahr ist, wenn Sie die C-Startroutine zählen, die Ihremain()
Funktion aufgerufen hat , ist dies nicht der Fall genau das, was du meinst, wenn du den Prozess beenden willst.Wenn Sie Ihr Programm von einer anderen Funktion aus beenden möchten, müssen
main()
Sie aufrufen . Wenn Sie dies auch konsequent tun, wird Ihr Code viel lesbarer und es wird für jeden viel einfacher, Ihren Code neu zu faktorisieren. dh Code kopiert zu einer anderen Funktion wird nicht wegen der zufälligen schlecht benehmen Aussagen , die sollten schon haben Anrufe.exit()
main()
main()
return
exit()
Wenn man all diese Punkte miteinander kombiniert, ist die Schlussfolgerung, dass es zumindest für C eine schlechte Angewohnheit ist , eine
return
Anweisung zu verwenden, um das Programm zu beendenmain()
.quelle
exit()
generell zu vermeiden , aber verwenden Sie es, wenn athrow
oderabort()
Alternativen in einem bestimmten Kontext nicht funktionieren. Vermeiden Sie dies jedoch besondersexit()
in main und verwenden Sie stattdessen return in main als typische Praxis.Bei einigen Compilern für ungewöhnliche Plattformen wird
exit()
das Argument möglicherweise in den Exit-Wert Ihres Programms übersetzt, während bei einer Rückgabe vonmain()
der Wert möglicherweise ohne Übersetzung direkt an die Host-Umgebung übergeben wird.Der Standard erfordert in diesen Fällen ein identisches Verhalten (insbesondere heißt es, dass die
int
Rückgabe von etwas, das mit kompatibelmain()
ist, dem Aufrufexit()
mit diesem Wert entsprechen sollte). Das Problem ist, dass verschiedene Betriebssysteme unterschiedliche Konventionen für die Interpretation der Exit-Werte haben. Auf vielen (VIELEN!) Systemen bedeutet 0 Erfolg und alles andere ist ein Fehler. Aber bei VMS bedeuten ungerade Werte Erfolg und gerade Misserfolg. Wenn Sie 0 von zurückgebenmain()
, wird einem VMS-Benutzer eine böse Nachricht über eine Zugriffsverletzung angezeigt. Es gab eigentlich keine Zugriffsverletzung - das war einfach die Standardnachricht, die dem Fehlercode 0 zugeordnet war.Dann kam ANSI und segnete
EXIT_SUCCESS
undEXIT_FAILURE
als Argumente, an die man weitergeben konnteexit()
. Die Norm sagt auch , dassexit(0)
sich verhalten sollten identischexit(EXIT_SUCCESS)
, so dass die meisten Implementierungen definierenEXIT_SUCCESS
zu0
.Der Standard daher bringen Sie in einer Bindung auf VMS, wie es läßt keinen einzigen Weg zurückzukehren Ausfall - Code, der den Wert 0 haben passiert.
Der VAX / VMS C-Compiler aus den frühen 1990er Jahren interpretierte daher den Rückgabewert von nicht
main()
, sondern gab einfach den Wert an die Hostumgebung zurück. Wenn Sie es jedoch verwendenexit()
würden, würde es das tun, was der Standard erfordert: ÜbersetzenEXIT_SUCCESS
(oder0
) in einen Erfolgscode undEXIT_FAILURE
in einen generischen Fehlercode. Um es zu benutzenEXIT_SUCCESS
, musste man es weitergebenexit()
, man konnte es nicht zurückgebenmain()
. Ich weiß nicht, ob modernere Versionen dieses Compilers dieses Verhalten beibehalten haben.Ein tragbares C-Programm, das früher so aussah:
Nebenbei: Wenn ich mich richtig erinnere, ist die VMS-Konvention für Exit-Werte nuancierter als ungerade / gerade. Tatsächlich werden so etwas wie die niedrigen drei Bits verwendet, um einen Schweregrad zu codieren. Im Allgemeinen zeigten die ungeraden Schweregrade jedoch Erfolg oder verschiedene Informationen an, und die geraden zeigten Fehler an.
quelle
returned
durchmain
unterschiedlich von dem Wert übergebenexit
- aber der Standard sagt ausdrücklich : „Wenn der Rückgabetyp dermain
Funktion ein Typ kompatibel istint
, eine Rückkehr aus dem ersten Aufruf dermain
Funktion entspricht dem Aufruf derexit
Funktion mit dem von dermain
Funktion als Argument zurückgegebenen Wert ". Das ist C11; C89 / C90 hatte fast den gleichen Wortlaut.EXIT_SUCCESS
, gab es keine Möglichkeit , eine plattformspezifische zurückzukehren Ausfall - Status mit dem Wert 0, die einige der Compiler der Ära behandeln Rückkehr von der Haupt kann, warum undexit()
anders.In C ist das Zurückkehren von
main
genau das Gleiche wie das Aufrufenexit
mit demselben Wert.Abschnitt 5.1.2.2.3 der C-Standardzustände :
Die Regeln für C ++ sind etwas anders, wie in anderen Antworten erwähnt.
quelle
Es gibt tatsächlich einen Unterschied zwischen
exit(0)
undreturn(0)
inmain
- wenn Ihremain
Funktion mehrmals aufgerufen wird.Das folgende Programm
Rennen wie
Wird zu folgender Ausgabe führen:
Jedoch dieses:
Gibt unabhängig von den Argumenten nichts aus.
Wenn Sie sicher sind, dass niemand Sie jemals
main
explizit anrufen wird , ist dies im Allgemeinen technisch gesehen kein großer Unterschied, aber klareren Code beizubehalten,exit
würde viel besser aussehen. Wenn Sie aus irgendeinem Grund anrufen möchten,main
sollten Sie es an Ihre Bedürfnisse anpassen.Apropos C.
quelle