Warum ist main()
eine benutzerdefinierte Funktion?
Wann werde ich verwenden void main()
und int main()
?
ANUP BISOYI
Warum ist main()
eine benutzerdefinierte Funktion?
Wann werde ich verwenden void main()
und int main()
?
Lundin
BEARBEITEN Diese Antwort ist nicht so vollständig, wie sie sein könnte, da sie den seltsamen Satz “oder anderweitig in einer implementierungsdefinierten Weise” nicht wirklich anspricht. Ich habe jetzt eine vollständigere Antwort geschrieben, die sich auch mit C90, C11 und C++ befasst. ENDE DER BEARBEITUNG
Hier ist, was die C-Norm sagt (ISO C 9899:1999):
5.1.2.1 Freistehende Umgebung
In einer freistehenden Umgebung (in der die Ausführung von C-Programmen ohne den Nutzen eines Betriebssystems stattfinden kann) sind Name und Typ der Funktion, die beim Programmstart aufgerufen wird, implementierungsdefiniert. / .. / Der Effekt der Programmbeendigung in einer freistehenden Umgebung ist implementierungsdefiniert.
5.1.2.2 Gehostete Umgebung
Eine gehostete Umgebung muss nicht bereitgestellt werden, muss aber, falls vorhanden, den folgenden Spezifikationen entsprechen.
5.1.2.2.1 Programmstart
Die beim Programmstart aufgerufene Funktion heißt main. Die Implementierung deklariert keinen Prototyp für diese Funktion. Es muss mit einem Rückgabetyp von int und ohne Parameter definiert werden:
int main(void) { /* … */ }
oder mit zwei Parametern (hier als argc und argv bezeichnet, obwohl beliebige Namen verwendet werden können, da sie lokal für die Funktion sind, in der sie deklariert sind):
int main(int argc, char* argv[]) { /* … */ }
Der Text im C++-Standard ist mehr oder weniger identisch. Bitte Beachten Sie, dass “Programmstart” im Text a ist Nebensatz in die gehostete Umgebung.
Das heisst:
Wenn Ihr Programm in einer hostlosen Umgebung läuft (Ihr Programm ist ein eingebettetes System oder ein Betriebssystem), kann es einen beliebigen Rückgabetyp haben. void main() ist am häufigsten.
Wenn Ihr Programm in einer gehosteten Umgebung (auf einem Betriebssystem) ausgeführt wird, verwenden Sie main() Muss gibt int zurück und kann zusätzliche Parameter haben.
+1, für die gültige Antwort. Aber vielleicht noch eine Erklärung. In freistehenden Umgebungen ist der Rückgabetyp von main
ist Umsetzung definiert: Dies bedeutet nicht, dass es Sache des Programmierers ist, dies zu entscheiden, aber dass es so ist auferlegt durch die Plattform. Das Compiler-Handbuch sollte dies angeben. In gehosteten Umgebungen besteht die Wahl tatsächlich zwischen den beiden angegebenen Alternativen für die Parameter. Wenn es Parameter gibt, müssen diese genau zwei sein und die angegebenen Typen haben. Übrigens scheint mir, dass Sie eine verpasst haben *
zum argv
.
– Jens Gustedt
14. März 2011 um 9:20 Uhr
Beim Überprüfen des Standards haben Sie tatsächlich die Fortsetzung des letzten Satzes des Abschnitts übersprungen: “oder gleichwertig;9) oder auf eine andere implementierungsdefinierte Weise.” Das bedeutet, dass die Compiler-Implementierung auch hier wieder eine andere Aufrufkonvention haben kann. Einige Compiler erlauben zB ein drittes Argument “char *envp[]”. Aber auch dies muss in der Compiler-Dokumentation angegeben werden.
– Jens Gustedt
14. März 2011 um 9:25 Uhr
Der C-Standard erlaubt den Rückgabetyp von main
etwas anderes sein als int
. Der Wortlaut von 5.1.2.1 ist mehrdeutig, aber 5.1.2.2.3 beginnt mit „Wenn der Rückgabetyp der hauptsächlich function ist ein Typ, der mit int kompatibel ist …”
– Keith Thompson
20. Februar 2012 um 10:12 Uhr
@KeithThompson 5.1.2.1 gibt eine freistehende Umgebung an, hat also nichts mit 5.1.2.2.3 zu tun, das nur für eine gehostete Umgebung gilt. Und ja, der Standard erlaubt implementierungsdefinierte Möglichkeiten, main zu deklarieren, sowie unspezifiziertes Verhalten, wenn ein anderer Typ als int zurückgegeben wird. Dies sind jedoch immer noch Entscheidungen, die vom Compiler-Implementierer und nicht vom Programmierer getroffen werden. Daher halte ich es für das Beste, alle derartigen Sonderfälle aus dieser Antwort herauszulassen.
– Ludin
20. Februar 2012 um 10:43 Uhr
@Lundin: Mein Punkt ist einfach, dass Sie in Ihrer Antwort eine sachlich falsche Aussage haben. Eine konforme C-Implementierung kann dokumentieren und zulassen void main(void)
. (Und das Verhalten, das Sie beschreiben, macht Turbo C nicht nicht konform; definierend void main()
wenn die Implementierung nicht dokumentiert, hat sie undefiniertes Verhalten, erfordert aber keine Diagnose.)
– Keith Thompson
20. Februar 2012 um 18:09 Uhr
Leichtigkeitsrennen im Orbit
Lundin hat Recht mit C, aber in C++ ist der Wortlaut ausreichend deutlich, um einen Unterschied zu machen:
[C++11: 3.6.1/1]:
Ein Programm muss eine globale Funktion enthalten, die aufgerufen wirdmain
das ist der vorgesehene Beginn des Programms. Es ist implementierungsabhängig, ob ein Programm in einer freistehenden Umgebung a definieren mussmain
Funktion.
[C++11: 3.6.1/2]:
Eine Implementierung darf die nicht vordefinierenmain
Funktion. Diese Funktion darf nicht überladen werden. Es muss einen Rückgabetyp von type habenint
aber ansonsten ist sein Typ implementierungsdefiniert [..]
Die erste fettgedruckte Passage überschreibt oder hebt die zweite nicht auf.
main
kehrt zurück int
in C++ immer.
Sie können verwenden void
… außer du kannst es nicht.
– Bartek Banachewicz
12. Februar 2013 um 11:17 Uhr
Und dann fährt 3.6.1/1 fort: “Note: In a freestanding environment, start-up and termination is implementation-defined
“. Ich weiß nicht, warum der Wortlaut in C ++ 11 geändert wurde, aber dies kann nur vernünftig interpretiert werden als “freistehende Implementierungen können main ganz nach Belieben deklarieren”. Für ein Programm ohne Betriebssystem ergibt dies keinen Sinn , oder für das Betriebssystem selbst, um einen int zurückzugeben. An wen würden sie den int zurückgeben?
– Ludin
12. Februar 2013 um 12:12 Uhr
@Lundin: Start und Beendigung können implementierungsdefiniert sein (also kann es sein, dass es nicht einmal passiert oder mit einer Funktion mit einem anderen Namen als main
oder auf andere Weise passieren), sondern wenn es da ist ist ein globales main
Funktion vorhanden, ihr Rückgabetyp ist int
. Immer. Dies wird durch die eindeutige Formulierung sehr deutlich.
– Leichtigkeitsrennen im Orbit
12. Februar 2013 um 12:21 Uhr
@LightnessRacesinOrbit Also mit anderen Worten, freistehende C++-Implementierungen sollten main() dann niemals implementieren, da es nutzlos ist? Typischerweise starten freistehende Systeme an einem hardwarespezifischen Einstiegspunkt (“Bootsektor” usw.), von wo aus das grundlegende Hardware-Setup sowie die statische Initialisierung usw. alles, was vor main () ausgeführt werden muss, ausgeführt werden. Und von dort rufen sie a void main()
. Sie möchten nicht zu Ihrem Einstiegspunkt zurückkehren. Wenn main den Typ int hätte, dann müsste die aufrufende Konvention möglicherweise erzwingen, dass ein nutzloser Garbage-int für immer auf dem Stack reserviert wird, was einfach dumm wäre.
– Ludin
12. Februar 2013 um 12:38 Uhr
@Lundin: Wenn eine freistehende Implementierung eine Einstiegspunktfunktion hat und sie sie aufrufen main
und es ist global, dann muss es einen Rückgabetyp haben int
. Es steht ihnen frei, es anders zu nennen und es sein zu lassen void
.
– Leichtigkeitsrennen im Orbit
12. Februar 2013 um 13:29 Uhr
Der Rückgabetyp für main
wird von der Implementierung bestimmt, nicht vom Programmierer. Überprüfen Sie Ihre Compiler-Dokumentation, um zu sehen, wofür die legalen Signaturen sind main
. Gehen Sie davon nicht aus void main()
Ist einer von ihnen. In einer gehosteten Umgebung main
kehrt normalerweise zurück int
. In einer freistehenden Umgebung darf der Einstiegspunkt nicht einmal benannt werden main
aber der Rückgabetyp wird immer noch von der Implementierung bestimmt, nicht vom Programmierer.
pmg
Es gibt 3 Situationen:
In 1. es muss keine benannte Funktion vorhanden sein main
überhaupt. Die Implementierung definiert, wie ein Programm startet.
In 2. Ein Programm beginnt mit der Ausführung bei einer Funktion mit dem Namen main
definiert mit einer der folgenden 2 “Signaturen”: int main(void)
oder int main(int argc, char **argv)
Im 3. Ein Programm beginnt mit der Ausführung bei einer Funktion mit dem Namen main
, definiert als von der Implementierung erlaubt. Diese Funktion muss zurückkehren int
Standardkonform sein. Zum Beispiel: int main(int argc, char **argv, char **envp)
oder int main(wchar_t**)
. Beachten Sie, dass Programme, die diese Formen verwenden, nicht unbedingt in allen gehosteten Implementierungen gültig sind (und für den ursprünglichen Autor ungültig werden können, wenn sich die Implementierung ändert).
Goldesel
Ursprünglich gab es in der C-Sprache keinen solchen Typ wie void
und deshalb musste die Funktion zurückkehren int
.
In der Praxis zurück int
ermöglicht es Ihnen, einen anderen Prozess aus Ihrem Prozess auszuführen (mithilfe von fork
und exec
) und wenn Sie das Rückgabeergebnis von diesem Prozess erhalten können, wissen Sie, ob es funktioniert hat oder nicht.
Viele Compiler unterstützen void main() nicht, daher sollten Sie immer int main() verwenden.
Die Art von jeden Die Definition von Nicht-Bibliotheksfunktionen bleibt dem Benutzer überlassen.
main
unterscheidet sich dadurch, dass die Auswahlmöglichkeiten geringer sind.– Keith Thompson
3. September 2013 um 2:02 Uhr