webentwicklung-frage-antwort-db.com.de

Was soll main () in C und C ++ zurückgeben?

646
Joel

Der Rückgabewert für main sollte angeben, wie das Programm beendet wurde. Normaler Exit wird im Allgemeinen durch einen 0-Rückgabewert von main dargestellt. Abnormales Verlassen wird normalerweise durch eine Rückkehr ungleich Null signalisiert, es gibt jedoch keinen Standard für die Interpretation von Codes ungleich Null. Wie auch von anderen angemerkt, ist void main() vom C++ - Standard ausdrücklich verboten und sollte nicht verwendet werden. Die gültigen C++ main Signaturen sind:

int main()

und

int main(int argc, char* argv[])

das ist äquivalent zu

int main(int argc, char** argv)

Es ist auch erwähnenswert, dass in C++ int main() ohne return-Anweisung belassen werden kann. Zu diesem Zeitpunkt wird standardmäßig 0 zurückgegeben. Dies gilt auch für ein C99-Programm. Ob return 0; weggelassen werden sollte oder nicht, ist umstritten. Der Bereich der gültigen Hauptsignaturen des C-Programms ist viel größer.

Auch bei der Funktion main spielt Effizienz keine Rolle. Es kann nur einmal eingegeben und verlassen werden (markiert den Start und das Ende des Programms), gemäß dem C++ - Standard. Für C ist der Fall anders und die erneute Eingabe von main() ist zulässig, sollte jedoch vermieden werden.

531
workmad3

Die akzeptierte Antwort scheint auf C++ ausgerichtet zu sein, daher habe ich mir überlegt, eine Antwort hinzuzufügen, die sich auf C bezieht, und die sich in einigen Punkten unterscheidet.

ISO/IEC 9899: 1989 (C90):

main() sollte wie folgt deklariert werden:

int main(void)
int main(int argc, char **argv)

Oder gleichwertig. Zum Beispiel entspricht int main(int argc, char *argv[]) dem zweiten. Außerdem kann der Rückgabetyp int weggelassen werden, da er standardmäßig verwendet wird.

Wenn eine Implementierung dies zulässt, kann main() auf andere Weise deklariert werden. Dadurch wird die Programmimplementierung jedoch definiert und ist nicht mehr streng konform.

Der Standard definiert 3 Werte für die Rückgabe, die streng konform sind (dh nicht auf dem durch die Implementierung definierten Verhalten beruhen): 0 und EXIT_SUCCESS für eine erfolgreiche Beendigung und EXIT_FAILURE für eine erfolglose Beendigung . Alle anderen Werte sind nicht standardisiert und die Implementierung definiert. main() muss am Ende eine explizite return -Anweisung haben, um undefiniertes Verhalten zu vermeiden.

Schließlich ist aus Standardsicht nichts falsch daran, main() von einem Programm aus aufzurufen.

ISO/IEC 9899: 1999 (C99):

Für C99 ist alles wie oben, außer:

  • Der Rückgabetyp int darf nicht weggelassen werden.
  • Sie können die return-Anweisung in main() weglassen. Wenn Sie dies tun und main() beendet ist, gibt es einen impliziten return 0.
155
Chris Young

Standard C - Gehostete Umgebung

Für eine gehostete Umgebung (das ist die normale) lautet der C11-Standard (ISO/IEC 9899: 2011):

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 dem Rückgabetyp 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 für die Funktion, in der sie deklariert sind, lokal sind):

int main(int argc, char *argv[]) { /* ... */ }

oder gleichwertig;10) oder auf eine andere durch die Implementierung definierte Weise.

Wenn sie deklariert sind, müssen die Parameter der Hauptfunktion die folgenden Bedingungen erfüllen:

  • Der Wert von argc darf nicht negativ sein.
  • argv[argc] soll ein Nullzeiger sein.
  • Wenn der Wert von argc größer als Null ist, enthalten die Array-Mitglieder argv[0] bis argv[argc-1] einschließlich Zeiger auf Zeichenfolgen, denen vor dem Programmstart von der Host-Umgebung implementierungsdefinierte Werte zugewiesen werden. Die Absicht besteht darin, die vor dem Programmstart ermittelten Programminformationen von einer anderen Stelle in der gehosteten Umgebung bereitzustellen. Ist die Host-Umgebung nicht in der Lage, Zeichenfolgen sowohl in Groß- als auch in Kleinbuchstaben mit Buchstaben zu versorgen, muss die Implementierung sicherstellen, dass die Zeichenfolgen in Kleinbuchstaben empfangen werden.
  • Wenn der Wert von argc größer als Null ist, repräsentiert die Zeichenfolge, auf die argv[0] zeigt, den Programmnamen. argv[0][0] ist das Nullzeichen, wenn der Programmname in der Host-Umgebung nicht verfügbar ist. Wenn der Wert von argc größer als eins ist, stellen die Zeichenfolgen, auf die argv[1] bis argv[argc-1] zeigen, die Programmparameter dar.
  • Die Parameter argc und argv sowie die Zeichenfolgen, auf die das Array argv verweist, müssen vom Programm geändert werden können und behalten ihre zuletzt gespeicherten Werte zwischen Programmstart und Programmende bei.

10) Somit kann int durch einen typisierten Namen ersetzt werden, der als int definiert ist, oder der Typ von argv kann als char **argv usw. geschrieben werden.

Programmabbruch in C99 oder C11

Der von main() zurückgegebene Wert wird implementierungsdefiniert an die 'Umgebung' übertragen.

5.1.2.2.3 Programmbeendigung

1 Wenn der Rückgabetyp der Funktion main mit dem Typ int kompatibel ist, entspricht die Rückkehr vom ersten Aufruf zur Funktion main dem Aufruf der Funktion exit mit der von der main -Funktion als Argument zurückgegebene Wert;11) Wenn Sie den } erreichen, der die Funktion main beendet, wird der Wert 0 zurückgegeben. Wenn der Rückgabetyp nicht mit int kompatibel ist, ist der an die Host-Umgebung zurückgegebene Beendigungsstatus nicht angegeben.

11) In Übereinstimmung mit 6.2.4 ist die Lebensdauer von Objekten mit der in main angegebenen automatischen Speicherdauer im ersteren Fall beendet, auch wenn dies im letzteren Fall nicht der Fall wäre.

Beachten Sie, dass 0 als "Erfolg" angegeben wird. Sie können EXIT_FAILURE und EXIT_SUCCESS von <stdlib.h> verwenden, wenn Sie dies vorziehen, aber 0 ist gut etabliert, und so ist 1. Siehe auch Exit-Codes größer als 255 - möglich? .

In C89 (und daher in Microsoft C) gibt es keine Anweisung darüber, was passiert, wenn die Funktion main() zurückgibt, aber keinen Rückgabewert angibt. es führt daher zu undefiniertem Verhalten.

7.22.4.4 Die Funktion exit

¶5 Schließlich wird die Steuerung an die Host-Umgebung zurückgegeben. Wenn der Wert von status Null oder EXIT_SUCCESS ist, wird eine implementierungsdefinierte Form des Status erfolgreiche Beendigung zurückgegeben. Wenn der Wert von statusEXIT_FAILURE ist, wird eine implementierungsdefinierte Form des Status nicht erfolgreiche Beendigung zurückgegeben. Andernfalls ist der zurückgegebene Status implementierungsdefiniert.

Standard C++ - Gehostete Umgebung

Der C++ 11-Standard (ISO/IEC 14882: 2011) besagt:

3.6.1 Hauptfunktion [basic.start.main]

¶1 Ein Programm muss eine globale Funktion namens main enthalten, die der festgelegte Start des Programms ist. [...]

¶2 Eine Implementierung soll die Hauptfunktion nicht vorgeben. Diese Funktion darf nicht überladen werden. Es muss einen Rückgabetyp vom Typ int haben, ansonsten ist der Typ durch die Implementierung definiert. Alle Implementierungen müssen die beiden folgenden Definitionen von main zulassen:

int main() { /* ... */ }

und

int main(int argc, char* argv[]) { /* ... */ }

In der letzteren Form ist argc die Anzahl der Argumente, die von der Umgebung, in der das Programm ausgeführt wird, an das Programm übergeben werden. Wenn argc ungleich Null ist, müssen diese Argumente in argv[0] bis argv[argc-1] als Zeiger auf die Anfangszeichen von nullterminierten Multibyte-Strings (NTMBSs) (17.5.2.1.4.2) und argv[0] als Zeiger auf das Anfangszeichen von angegeben werden Ein NTMBS, der den Namen darstellt, der zum Aufrufen des Programms oder von "" verwendet wird. Der Wert von argc darf nicht negativ sein. Der Wert von argv[argc] muss 0 sein. [Hinweis: Es wird empfohlen, nach argv weitere (optionale) Parameter hinzuzufügen. —Ende Notiz]

¶3 Die Funktion main darf nicht in einem Programm verwendet werden. Die Verknüpfung (3.5) von main ist implementierungsdefiniert. [...]

¶5 Eine return-Anweisung in main bewirkt, dass die main-Funktion verlassen wird (alle Objekte mit automatischer Speicherdauer werden zerstört) und std::exit mit dem Rückgabewert als Argument aufgerufen wird. Wenn die Steuerung das Ende von main erreicht, ohne dass eine return-Anweisung auftritt, wird sie ausgeführt

return 0;

Der C++ - Standard sagt explizit "Es [die Hauptfunktion] soll einen Rückgabetyp vom Typ int haben, aber ansonsten ist sein Typ durch die Implementierung definiert" und erfordert, dass dieselben zwei Signaturen wie der C-Standard als Optionen unterstützt werden. Daher ist ein 'void main ()' vom C++ - Standard direkt nicht zulässig, obwohl nichts getan werden kann, um eine nicht standardmäßige Implementierung zu stoppen, die Alternativen zulässt. Beachten Sie, dass C++ es dem Benutzer verbietet, main aufzurufen (der C-Standard jedoch nicht).

Es gibt einen Absatz von §18.5 Start und Beendigung im C++ 11-Standard, der identisch ist mit dem Absatz von §7.22.4.4 Die exit -Funktion im C11-Standard (oben zitiert), abgesehen von einer Fußnote (die einfach dokumentiert, dass EXIT_SUCCESS und EXIT_FAILURE in <cstdlib> definiert sind).

Standard C - Gemeinsame Erweiterung

Klassischerweise unterstützen Unix-Systeme eine dritte Variante:

int main(int argc, char **argv, char **envp) { ... }

Das dritte Argument ist eine nullterminierte Liste von Zeigern auf Zeichenfolgen, von denen jede eine Umgebungsvariable ist, die einen Namen, ein Gleichheitszeichen und einen Wert hat (möglicherweise leer). Wenn Sie dies nicht verwenden, können Sie dennoch über 'extern char **environ;' auf die Umgebung zugreifen. Lange Zeit hatte das keinen Header, der es deklarierte, aber der POSIX 2008-Standard verlangt nun, dass es in <unistd.h> deklariert wird.

Dies wird von der C-Norm als gemeinsame Erweiterung anerkannt, die in Anhang J dokumentiert ist:

J.5.1 Umgebungsargumente

¶1 In einer gehosteten Umgebung erhält die Hauptfunktion ein drittes Argument, char *envp[], das auf ein nullterminiertes Array von Zeigern auf char verweist, von denen jedes auf eine Zeichenfolge verweist, die Informationen zur Umgebung für diese Ausführung enthält des Programms (5.1.2.2.1).

Microsoft C

Der Microsoft VS 201 Compiler ist interessant. Die Website sagt:

Die Deklarationssyntax für main lautet

 int main();

oder optional

int main(int argc, char *argv[], char *envp[]);

Alternativ können die Funktionen main und wmain als zurückgebend void deklariert werden (kein Rückgabewert). Wenn Sie main oder wmain als "return" deklarieren, können Sie mithilfe einer return-Anweisung keinen Exit-Code an den übergeordneten Prozess oder das übergeordnete Betriebssystem zurückgeben. Um einen Exit-Code zurückzugeben, wenn main oder wmain als void deklariert ist, müssen Sie die Funktion exit verwenden.

Mir ist nicht klar, was passiert (welcher Exit-Code wird an das übergeordnete oder das Betriebssystem zurückgegeben), wenn ein Programm mit void main() beendet wird - und die MS-Website ist auch still.

Interessanterweise schreibt MS die Version von main() mit zwei Argumenten nicht vor, die die C- und C++ - Standards erfordern. Es wird nur eine Form mit drei Argumenten vorgeschrieben, wobei das dritte Argument char **envp ist, ein Zeiger auf eine Liste von Umgebungsvariablen.

Die Microsoft-Seite listet auch einige andere Alternativen auf - wmain(), für die breite Zeichenfolgen verwendet werden, und weitere.

Die Microsoft Visual Studio 2005 -Version von diese Seite listet void main() nicht als Alternative auf. Die Versionen von Microsoft Visual Studio 2008 ab.

Standard C - Freistehende Umgebung

Wie bereits erwähnt, gelten die oben genannten Anforderungen für gehostete Umgebungen. Wenn Sie mit einer freistehenden Umgebung arbeiten (die Alternative zu einer gehosteten Umgebung), hat der Standard viel weniger zu sagen. In einer freistehenden Umgebung muss die beim Programmstart aufgerufene Funktion nicht main heißen, und der Rückgabetyp unterliegt keinen Einschränkungen. Der Standard sagt:

5.1.2 Ausführungsumgebungen

Es werden zwei Ausführungsumgebungen definiert: freistehend und gehostet. In beiden Fällen tritt der Programmstart auf, wenn eine bestimmte C-Funktion von der Ausführungsumgebung aufgerufen wird. Alle Objekte mit statischer Speicherdauer müssen vor dem Programmstart initialisiert (auf ihre Anfangswerte gesetzt) ​​werden. Die Art und der Zeitpunkt einer solchen Initialisierung sind ansonsten nicht spezifiziert. Die Programmbeendigung gibt die Kontrolle an die Ausführungsumgebung zurück.

5.1.2.1 Freistehende Umgebung

In einer freistehenden Umgebung (in der die Ausführung von C-Programmen ohne Betriebssystem erfolgen kann) werden Name und Typ der beim Programmstart aufgerufenen Funktion durch die Implementierung festgelegt. Alle Bibliothekseinrichtungen, die einem freistehenden Programm zur Verfügung stehen, sind von der Implementierung abhängig.

Die Auswirkung der Programmbeendigung in einer freistehenden Umgebung ist implementierungsspezifisch.

Der Verweis auf Klausel 4 Konformität bezieht sich auf Folgendes:

¶5 Ein streng konformes Programm darf nur die Merkmale der Sprache und Bibliothek verwenden, die in dieser Internationalen Norm festgelegt sind.3) Es darf keine Ausgabe produzieren, die von einem nicht spezifizierten, undefinierten oder implementierungsdefinierten Verhalten abhängig ist, und es darf keine minimale Implementierungsgrenze überschreiten.

¶6 Die beiden Formen der konformen Implementierung sind Hosted und Freestanding . Eine konforme gehostete Implementierung muss jedes streng konforme Programm akzeptieren. Eine konforme freistehende Implementierung muss jedes streng konforme Programm akzeptieren, in dem die Verwendung der in der Bibliotheksklausel (Klausel 7) angegebenen Funktionen auf den Inhalt der Standardüberschriften <float.h>, <iso646.h> beschränkt ist. , <limits.h>, <stdalign.h>, <stdarg.h>, <stdbool.h>, <stddef.h>, <stdint.h> und <stdnoreturn.h>. Eine konforme Implementierung kann Erweiterungen (einschließlich zusätzlicher Bibliotheksfunktionen) aufweisen, sofern diese das Verhalten eines streng konformen Programms nicht ändern.4)

¶7 Ein konformes Programm ist ein Programm, das für eine konforme Implementierung akzeptabel ist.5)

3) Ein streng konformes Programm kann bedingte Funktionen verwenden (siehe 6.10.8.3), vorausgesetzt, die Verwendung wird durch eine entsprechende Vorverarbeitungsrichtlinie für bedingte Einschlüsse unter Verwendung des zugehörigen Makros geschützt. Zum Beispiel:

#ifdef __STDC_IEC_559__ /* FE_UPWARD defined */
    /* ... */
    fesetround(FE_UPWARD);
    /* ... */
#endif

4) Dies impliziert, dass eine konforme Implementierung keine anderen Bezeichner als die in dieser Internationalen Norm ausdrücklich reservierten reserviert.

5) Streng konforme Programme sollen zwischen konformen Implementierungen maximal portierbar sein. Übereinstimmende Programme können von nicht portierbaren Merkmalen einer übereinstimmenden Implementierung abhängen.

Es fällt auf, dass der einzige Header, der in einer freistehenden Umgebung benötigt wird, der tatsächlich Funktionen definiert, <stdarg.h> ist (und selbst diese können - und sind es oftmals - nur Makros).

Standard C++ - Freistehende Umgebung

So wie der C-Standard sowohl gehostete als auch freistehende Umgebungen erkennt, gilt dies auch für den C++ - Standard. (Zitate aus ISO/IEC 14882: 2011.)

1.4 Implementierungskonformität [intro.compliance]

¶7 Es werden zwei Arten von Implementierungen definiert: eine gehostete Implementierung und eine freistehende Implementierung . Für eine gehostete Implementierung definiert diese Internationale Norm die Menge der verfügbaren Bibliotheken. Eine freistehende Implementierung ist eine Implementierung, bei der die Ausführung ohne die Vorteile eines Betriebssystems erfolgen kann. Sie verfügt über einen implementierungsdefinierten Satz von Bibliotheken, der bestimmte Bibliotheken zur Sprachunterstützung enthält (17.6.1.3).

¶8 Eine konforme Implementierung kann Erweiterungen (einschließlich zusätzlicher Bibliotheksfunktionen) aufweisen, sofern diese das Verhalten eines wohlgeformten Programms nicht ändern. Es sind Implementierungen erforderlich, um Programme zu diagnostizieren, die solche Erweiterungen verwenden, die gemäß dieser Internationalen Norm fehlerhaft sind. Danach können sie jedoch solche Programme kompilieren und ausführen.

¶9 Jede Implementierung muss eine Dokumentation enthalten, die alle von ihr nicht unterstützten bedingt unterstützten Konstrukte identifiziert und alle länderspezifischen Merkmale definiert.3

3) Diese Dokumentation definiert auch das implementierungsdefinierte Verhalten. siehe 1.9.

17.6.1.3 Freistehende Implementierungen [Compliance]

Es werden zwei Arten von Implementierungen definiert: gehostet und freistehend (1.4). Für eine gehostete Implementierung beschreibt diese Internationale Norm die verfügbaren Header.

Eine freistehende Implementierung verfügt über eine implementierungsdefinierte Gruppe von Headern. Dieser Satz muss mindestens die in Tabelle 16 aufgeführten Überschriften enthalten.

Die gelieferte Version des Headers <cstdlib> muss mindestens die Funktionen abort, atexit, at_quick_exit, exit und quick_exit (18.5) deklarieren. Die anderen in dieser Tabelle aufgeführten Header müssen die gleichen Anforderungen erfüllen wie für eine gehostete Implementierung.

Tabelle 16 - C++ - Header für freistehende Implementierungen

Subclause                           Header(s)
                                    <ciso646>
18.2  Types                         <cstddef>
18.3  Implementation properties     <cfloat> <limits> <climits>
18.4  Integer types                 <cstdint>
18.5  Start and termination         <cstdlib>
18.6  Dynamic memory management     <new>
18.7  Type identification           <typeinfo>
18.8  Exception handling            <exception>
18.9  Initializer lists             <initializer_list>
18.10 Other runtime support         <cstdalign> <cstdarg> <cstdbool>
20.9  Type traits                   <type_traits>
29    Atomics                       <atomic>

Was ist mit der Verwendung von int main() in C?

Der Standard §5.1.2.2.1 des C11-Standards zeigt die bevorzugte Notation - int main(void) -, aber es gibt auch zwei Beispiele im Standard, die int main() zeigen: §6.5.3.4 ¶8 und §6.7.6.3 ¶2 . Nun ist es wichtig anzumerken, dass Beispiele nicht „normativ“ sind. Sie sind nur zur Veranschaulichung. Wenn es in den Beispielen Fehler gibt, wirken sich diese nicht direkt auf den Haupttext der Norm aus. Das heißt, sie sind ein starkes Indiz für das erwartete Verhalten. Wenn der Standard also int main() in einem Beispiel enthält, deutet dies darauf hin, dass int main() nicht verboten ist, auch wenn dies nicht die bevorzugte Schreibweise ist.

6.5.3.4 Die Operatoren sizeof und _Alignof

¶8 BEISPIEL 3 In diesem Beispiel wird die Größe eines Arrays variabler Länge berechnet und von einer Funktion zurückgegeben:

#include <stddef.h>

size_t fsize3(int n)
{
    char b[n+3]; // variable length array
    return sizeof b; // execution time sizeof
}
int main()
{
    size_t size;
    size = fsize3(10); // fsize3 returns 13
    return 0;
}
110

Ich glaube, dass main() entweder EXIT_SUCCESS oder EXIT_FAILURE zurückgeben sollte. Sie sind in stdlib.h definiert.

59
dmityugov

Beachten Sie, dass die C- und C++ - Standards zwei Arten von Implementierungen definieren: freistehende und gehostete.

  • gehostete C90-Umgebung

    Zulässige Formen 1:

    int main (void)
    int main (int argc, char *argv[])
    
    main (void)
    main (int argc, char *argv[])
    /*... etc, similar forms with implicit int */
    

    Bemerkungen:

    Die ersten beiden werden explizit als zulässige Formulare angegeben, die anderen sind implizit zulässig, da C90 "implicit int" für Rückgabetyp- und Funktionsparameter zulässt. Keine andere Form ist erlaubt.

  • C90 freistehende Umgebung

    Jede Form oder Name der Hauptleitung ist erlaubt 2.

  • gehostete C99-Umgebung

    Zulässige Formen 3:

    int main (void)
    int main (int argc, char *argv[])
    /* or in some other implementation-defined manner. */
    

    Bemerkungen:

    C99 hat "implicit int" entfernt, so dass main() nicht mehr gültig ist.

    Ein seltsamer, mehrdeutiger Satz "oder auf eine andere durch die Implementierung definierte Weise" wurde eingeführt. Dies kann entweder als "die Parameter für int main() können variieren" interpretiert werden oder als "main kann jede implementierungsdefinierte Form haben".

    Einige Compiler haben beschlossen, den Standard auf die letztere Weise zu interpretieren. Man kann wohl nicht ohne weiteres behaupten, dass sie sich nicht strikt an die Norm halten, indem man sie an sich zitiert, da sie nicht eindeutig ist.

    Es war jedoch wahrscheinlich (?) Nicht die Absicht dieses neuen Satzes, völlig wilde Formen von main() zuzulassen. Das C99-Grundprinzip (nicht normativ) impliziert, dass der Satz auf zusätzliche Parameter für int main verweist. 4.

    Der Abschnitt zum Beenden des Programms für gehostete Umgebungen geht jedoch weiter auf den Fall ein, dass main nicht int zurückgibt 5. Obwohl dieser Abschnitt nicht normativ dafür ist, wie main deklariert werden soll, impliziert er definitiv, dass main auch auf gehosteten Systemen vollständig implementierungsdefiniert deklariert werden kann.

  • C99 freistehende Umgebung

    Jede Form oder Name der Hauptleitung ist erlaubt 6.

  • C11 gehostete Umgebung

    Zulässige Formen 7:

    int main (void)
    int main (int argc, char *argv[])
    /* or in some other implementation-defined manner. */
    
  • C11 freistehende Umgebung

    Jede Form oder Name der Hauptleitung ist erlaubt 8.


Beachten Sie, dass int main() in keiner der obigen Versionen als gültiges Formular für eine gehostete Implementierung von C aufgeführt wurde. In C haben () und (void) im Gegensatz zu C++ unterschiedliche Bedeutungen. Ersteres ist ein veraltetes Merkmal, das aus der Sprache entfernt werden kann. Siehe C11 zukünftige Sprachanweisungen:

6.11.6 Funktionsdeklaratoren

Die Verwendung von Funktionsdeklaratoren mit leeren Klammern (keine Parameter-Typdeklaratoren im Prototypformat) ist eine veraltete Funktion.


  • Gehostete C++ 03-Umgebung

    Zulässige Formen 9:

    int main ()
    int main (int argc, char *argv[])
    

    Bemerkungen:

    Beachten Sie die leere Klammer in dem ersten Formular. C++ und C unterscheiden sich in diesem Fall, da dies in C++ bedeutet, dass die Funktion keine Parameter akzeptiert. In C bedeutet dies jedoch, dass jeder Parameter verwendet werden kann.

  • C++ 03 freistehende Umgebung

    Der Name der beim Start aufgerufenen Funktion ist implementierungsspezifisch. Wenn es main() heißt, muss es den angegebenen Formen folgen 10:

    // implementation-defined name, or 
    int main ()
    int main (int argc, char *argv[])
    
  • Gehostete C++ 11-Umgebung

    Zulässige Formen 11:

    int main ()
    int main (int argc, char *argv[])
    

    Bemerkungen:

    Der Text der Norm wurde geändert, hat aber die gleiche Bedeutung.

  • C++ 11 freistehende Umgebung

    Der Name der beim Start aufgerufenen Funktion ist implementierungsspezifisch. Wenn es main() heißt, muss es den angegebenen Formen folgen 12:

    // implementation-defined name, or 
    int main ()
    int main (int argc, char *argv[])
    

Referenzen

  1. ANSI X3.159-1989 2.1.2.2 Gehostete Umgebung. "Programmstart"

    Die beim Programmstart aufgerufene Funktion heißt main. Die Implementierung deklariert keinen Prototyp für diese Funktion. Es muss mit dem Rückgabetyp 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 für die Funktion, in der sie deklariert sind, lokal sind):

    int main(int argc, char *argv[]) { /* ... */ }
    
  2. ANSI X3.159-1989 2.1.2.1 Freistehende Umgebung:

    In einer freistehenden Umgebung (in der die Ausführung von C-Programmen ohne Betriebssystem erfolgen kann) werden Name und Typ der beim Programmstart aufgerufenen Funktion durch die Implementierung festgelegt.

  3. ISO 9899: 1999 5.1.2.2 Gehostete Umgebung -> 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 dem Rückgabetyp 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 für die Funktion, in der sie deklariert sind, lokal sind):

    int main(int argc, char *argv[]) { /* ... */ }
    

    oder gleichwertig; 9) oder auf eine andere durch die Implementierung definierte Weise.

  4. Begründung für den internationalen Standard - Programmiersprachen - C, Revision 5.10. 5.1.2.2 Gehostete Umgebung -> 5.1.2.2.1 Programmstart

    Das Verhalten der Argumente für main und des Zusammenspiels von exit, main und atexit (siehe §7.20.4.2) wurde kodiert, um eine unerwünschte Vielfalt bei der Darstellung von argv-Zeichenfolgen und der Bedeutung der von main zurückgegebenen Werte einzudämmen.

    Die Angabe von argc und argv als Argumente für main erkennt eine umfangreiche frühere Praxis an. argv [argc] muss ein Nullzeiger sein, um eine redundante Prüfung für das Ende der Liste bereitzustellen, auch auf der Grundlage der üblichen 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.) In diesem Sonderfall wird einfach die weit verbreitete Praxis erkannt, die Argumente für main wegzulassen, wenn das Programm nicht auf die Programmargumentzeichenfolgen zugreift. Während viele Implementierungen mehr als zwei Argumente für main unterstützen, ist eine solche Praxis durch den Standard weder gesegnet noch verboten. Ein Programm, das main mit drei Argumenten definiert, ist nicht genau konform (siehe §J.5.1.).

  5. ISO 9899: 1999 5.1.2.2 Gehostete Umgebung -> 5.1.2.2.3 Programmbeendigung

    Wenn der Rückgabetyp der Hauptfunktion mit int kompatibel ist, entspricht eine Rückgabe vom ersten Aufruf an die Hauptfunktion dem Aufrufen der Exit-Funktion mit dem von der Hauptfunktion als Argument zurückgegebenen Wert; 11) Erreichen des }, das die Hauptfunktion beendet, gibt den Wert 0 zurück. Wenn der Rückgabetyp nicht mit int kompatibel ist, ist der an die Host-Umgebung zurückgegebene Beendigungsstatus nicht angegeben.

  6. ISO 9899: 1999 5.1.2.1 Freistehende Umgebung

    In einer freistehenden Umgebung (in der die Ausführung von C-Programmen ohne Betriebssystem erfolgen kann) werden Name und Typ der beim Programmstart aufgerufenen Funktion durch die Implementierung festgelegt.

  7. ISO 9899: 2011 5.1.2.2 Gehostete Umgebung -> 5.1.2.2.1 Programmstart

    Dieser Abschnitt ist identisch mit dem oben genannten C99.

  8. ISO 9899: 1999 5.1.2.1 Freistehende Umgebung

    Dieser Abschnitt ist identisch mit dem oben genannten C99.

  9. ISO 14882: 2003 3.6.1 Hauptfunktion

    Eine Implementierung soll die Hauptfunktion nicht vorgeben. Diese Funktion darf nicht überladen werden. Es muss einen Rückgabetyp vom Typ int haben, ansonsten ist der Typ implementierungsdefiniert. Alle Implementierungen müssen die beiden folgenden Definitionen von main zulassen:

    int main() { /* ... */ }
    

    und

    int main(int argc, char* argv[]) { /* ... */ }
    
  10. ISO 14882: 2003 3.6.1 Hauptfunktion

    Durch die Implementierung wird festgelegt, ob ein Programm in einer freistehenden Umgebung erforderlich ist, um eine Hauptfunktion zu definieren.

  11. ISO 14882: 2011 3.6.1 Hauptfunktion

    Eine Implementierung soll die Hauptfunktion nicht vorgeben. Diese Funktion darf nicht überladen werden. Es muss einen Rückgabetyp vom Typ int haben, ansonsten ist der Typ implementierungsdefiniert. Alle Implementierungen müssen beides ermöglichen

    - eine Funktion von () returning int und

    - eine Funktion von (int, Zeiger auf Zeiger auf Zeichen), die int zurückgibt

    als die Art der Haupt (8.3.5).

  12. ISO 14882: 2011 3.6.1 Hauptfunktion

    Dieser Abschnitt ist identisch mit dem oben genannten Abschnitt in C++ 03.

38
Lundin

Bei Erfolg 0 und bei Fehlern ungleich Null zurückgeben. Dies ist der Standard, der von UNIX- und DOS-Skripten verwendet wird, um herauszufinden, was mit Ihrem Programm geschehen ist.

29
Lou Franco

main() In C89 und K & R C sind nicht spezifizierte Rückgabetypen standardmäßig auf "int" eingestellt.

return 1? return 0?
  1. Wenn Sie in int main() keine return-Anweisung schreiben, gibt das schließende { standardmäßig 0 zurück.

  2. return 0 oder return 1 werden vom übergeordneten Prozess empfangen. In einer Shell geht es in eine Shell-Variable über, und wenn Sie Ihr Programm von einer Shell aus ausführen und diese Variable nicht verwenden, müssen Sie sich keine Gedanken über den Rückgabewert von main() machen.

Siehe Wie kann ich herausfinden, was meine Hauptfunktion zurückgegeben hat? .

$ ./a.out
$ echo $?

Auf diese Weise können Sie sehen, dass es die Variable $? ist, die das niedrigstwertige Byte des Rückgabewerts von main() empfängt.

Bei Unix- und DOS-Skripten werden normalerweise return 0 bei Erfolg und ein Fehler ungleich Null zurückgegeben. Dies ist der Standard, der von Unix- und DOS-Skripten verwendet wird, um herauszufinden, was mit Ihrem Programm passiert ist und um den gesamten Ablauf zu steuern.

8
Jeegar Patel

Beachten Sie, dass einige Betriebssysteme (Windows) den zurückgegebenen Wert auf ein einzelnes Byte (0-255) kürzen, obwohl Sie ein int zurückgeben.

7
Ferruccio

Der Rückgabewert kann vom Betriebssystem verwendet werden, um zu überprüfen, wie das Programm geschlossen wurde.

Rückgabewert 0 bedeutet normalerweise OK in den meisten Betriebssystemen (die, an die ich sowieso denken kann).

Es kann auch überprüft werden, wenn Sie einen Prozess selbst aufrufen und prüfen, ob das Programm ordnungsgemäß beendet und beendet wurde.

Es ist NICHT nur eine Programmierkonvention.

4
Yochai Timmer

Der Rückgabewert von main() zeigt, wie das Programm beendet wurde. Wenn der Rückgabewert zero ist, bedeutet dies, dass die Ausführung erfolgreich war, während ein Wert ungleich Null anzeigt, dass bei der Ausführung ein Fehler aufgetreten ist.

3
Fahad Uddin

Auslassen return 0

Wenn ein C- oder C++ - Programm das Ende von main erreicht, generiert der Compiler automatisch Code, um 0 zurückzugeben, sodass return 0; nicht explizit am Ende von main stehen muss.

Hinweis: Wenn ich diesen Vorschlag mache, folgen fast immer zwei Arten von Kommentaren: "Das wusste ich nicht." oder "Das ist ein schlechter Rat!" Mein Grundgedanke ist, dass es sicher und nützlich ist, sich auf das vom Standard ausdrücklich unterstützte Compilerverhalten zu verlassen. Für C seit C99; siehe ISO/IEC 9899: 1999, Abschnitt 5.1.2.2.3:

[...] Eine Rückkehr vom ersten Aufruf der Funktion main entspricht dem Aufruf der Funktion exit mit dem von der Funktion main als Argument zurückgegebenen Wert. Das Erreichen von }, das die Funktion main beendet, gibt den Wert 0 zurück.

Für C++ seit dem ersten Standard im Jahr 1998; siehe ISO/IEC 14882: 1998, Abschnitt 3.6.1:

Wenn die Steuerung das Ende von main erreicht, ohne auf eine return-Anweisung zu stoßen, wird return 0 ausgeführt.

Alle Versionen beider Standards (C99 und C++ 98) haben seitdem die gleiche Idee beibehalten. Wir stützen uns auf automatisch generierte Memberfunktionen in C++, und nur wenige Leute schreiben explizite return; -Anweisungen am Ende einer void -Funktion. Gründe gegen das Weglassen scheinen sich auf "es sieht komisch aus" zu beschränken. Wenn Sie, wie ich, neugierig sind auf die Gründe für die Änderung des C-Standards lesen Sie diese Frage . Beachten Sie auch, dass dies in den frühen 1990er Jahren als "schlampige Praxis" galt, da es sich zu dieser Zeit um undefiniertes Verhalten handelte (obwohl es weitgehend unterstützt wurde).

Darüber hinaus enthält C++ Core Guidelines mehrere Instanzen des Weglassens von return 0; am Ende von main und keine Instanzen, in denen eine explizite Rückgabe geschrieben ist. Obwohl es in diesem Dokument noch keine spezifische Richtlinie zu diesem bestimmten Thema gibt, scheint dies zumindest eine stillschweigende Bestätigung der Praxis zu sein.

Also befürworte ich es wegzulassen; andere stimmen nicht überein (oft vehement!) Wenn Sie auf Code stoßen, der ihn nicht enthält, wissen Sie auf jeden Fall, dass er ausdrücklich vom Standard unterstützt wird, und Sie wissen, was er bedeutet.

3
Edward

Ich hatte den Eindruck, dass der Standard angibt, dass main keinen Rückgabewert benötigt, da eine erfolgreiche Rückgabe auf dem Betriebssystem basiert (Null in einer konnte entweder ein Erfolg oder ein Misserfolg in einer anderen sein) Compiler, um die erfolgreiche Rückkehr selbst einzufügen.

Normalerweise gebe ich jedoch 0 zurück.

2
graham.reeds

Die Rückgabe von 0 sollte dem Programmierer mitteilen, dass das Programm den Job erfolgreich beendet hat.

2

Was ist der richtige (effizienteste) Weg, um die main () - Funktion in C und C++ zu definieren - int main () oder void main () - und warum?

Diese Worte "(am effizientesten)" ändern nichts an der Frage. Sofern Sie sich nicht in einer freistehenden Umgebung befinden, gibt es eine allgemein korrekte Möglichkeit, main() zu deklarieren, und zwar als returning int.

Was soll main() in C und C++ zurückgeben?

Es ist nicht das, was solltemain() zurückgibt, es ist das, was tutmain() zurückgibt. main() ist natürlich eine Funktion, die jemand anderes aufruft. Sie haben keine Kontrolle über den Code, der main() aufruft. Daher müssen Sie main() mit einer typkorrekten Signatur deklarieren, die dem Aufrufer entspricht. Sie haben einfach keine andere Wahl. Sie müssen sich nicht fragen, was mehr oder weniger effizient ist, was besser oder schlechter ist oder so, denn die Antwort ist für Sie nach C- und C + -Standards bereits perfekt definiert. Folge ihnen einfach.

Wenn int main () dann 1 oder 0 zurückgeben?

0 für Erfolg, ungleich Null für Misserfolg. Wieder nicht etwas, das Sie auswählen müssen (oder müssen): Es wird durch die Schnittstelle definiert, an die Sie sich anpassen sollen.

1
Steve Summit

Wenn Sie wirklich Probleme im Zusammenhang mit der Effizienz der Rückgabe einer Ganzzahl von einem Prozess haben, sollten Sie wahrscheinlich vermeiden, diesen Prozess so oft aufzurufen, dass dieser Rückgabewert zu einem Problem wird.

Wenn Sie dies tun (einen Prozess so oft aufrufen), sollten Sie eine Möglichkeit finden, Ihre Logik direkt im Aufrufer oder in einer DLL -Datei abzulegen, ohne jedem Aufruf einen bestimmten Prozess zuzuweisen. Die mehrfachen Prozesszuordnungen bringen Ihnen in diesem Fall das relevante Effizienzproblem.

Wenn Sie nur wissen möchten, ob die Rückgabe von 0 mehr oder weniger effizient ist als die Rückgabe von 1, kann dies in einigen Fällen vom Compiler abhängen, aber im Allgemeinen unter der Annahme, dass sie aus derselben Quelle (lokal, Feld, Konstante, eingebettet) gelesen werden im Code, Funktionsergebnis usw.) benötigt es genau die gleiche Anzahl von Taktzyklen.

1
Luca C.

Was zurückgegeben werden soll, hängt davon ab, was Sie mit der ausführbaren Datei tun möchten. Wenn Sie Ihr Programm beispielsweise mit einer Befehlszeilen-Shell verwenden, müssen Sie für einen Erfolg 0 und für einen Fehler ungleich Null zurückgeben. Dann können Sie das Programm abhängig vom Ergebnis Ihres Codes in Shells mit bedingter Verarbeitung verwenden. Sie können auch einen beliebigen Wert ungleich Null gemäß Ihrer Interpretation zuweisen, z. B. für kritische Fehler. Verschiedene Programm-Exit-Punkte könnten ein Programm mit unterschiedlichen Exit-Werten beenden. Dieser Wert steht der aufrufenden Shell zur Verfügung, die anhand des zurückgegebenen Werts entscheiden kann, was zu tun ist. Wenn der Code nicht für die Verwendung mit Shells vorgesehen ist und der zurückgegebene Wert niemanden stört, wird er möglicherweise weggelassen. Ich persönlich benutze die Signatur int main (void) { .. return 0; .. }

1
phoxis

Hier ist eine kleine Demonstration der Verwendung von Rückkehrcodes ...

Bei Verwendung der verschiedenen Tools, die das Linux-Terminal zur Verfügung stellt, kann der Rückkehrcode beispielsweise zur Fehlerbehandlung nach Abschluss des Vorgangs verwendet werden. Stellen Sie sich vor, dass die folgende Textdatei myfile vorhanden ist:

Dies ist ein Beispiel, um zu überprüfen, wie grep funktioniert.

Wenn Sie den Befehl grep ausführen, wird ein Prozess erstellt. Sobald es durch ist (und nicht kaputt gegangen ist), gibt es einen Code zwischen 0 und 255 zurück. Zum Beispiel:

$ grep order myfile

Wenn Sie tun

$ echo $?
$ 0

du bekommst eine 0. Warum? Weil grep eine Übereinstimmung gefunden und einen Exit-Code 0 zurückgegeben hat, was der übliche Wert für das erfolgreiche Beenden ist. Probieren wir es noch einmal aus, aber mit etwas, das nicht in unserer Textdatei enthalten ist und daher keine Übereinstimmung findet:

$ grep foo myfile
$ echo $?
$ 1

Da grep das Token "foo" nicht mit dem Inhalt unserer Datei abgleichen konnte, ist der Rückgabecode 1 (dies ist der übliche Fall, wenn ein Fehler auftritt, aber wie oben angegeben, stehen Ihnen zahlreiche Werte zur Auswahl).

Das folgende Bash-Skript (geben Sie es einfach in ein Linux-Terminal ein), obwohl es sehr einfach ist, sollte eine Vorstellung von der Fehlerbehandlung vermitteln:

$ grep foo myfile
$ CHECK=$?
$ [ $CHECK -eq 0] && echo 'Match found'
$ [ $CHECK -ne 0] && echo 'No match was found'
$ No match was found

Nach der zweiten Zeile wird nichts an das Terminal ausgegeben, seit "foo" grep auf 1 gesetzt hat und wir prüfen, ob der Rückkehrcode von grep gleich 0 war. Die zweite bedingte Anweisung gibt ihre Nachricht in der letzten Zeile wieder, da sie aufgrund von CHECK wahr ist == 1.

Wie Sie sehen können, wenn Sie diesen und jenen Prozess aufrufen, ist es manchmal wichtig zu sehen, was zurückgegeben wurde (durch den Rückgabewert von main ()).

0
rbaleksandar