Standard C - Hosted Environment
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 wird benannt 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 bezeichnet argv
, 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[]) { /* ... */ }
oder gleichwertig; 10) oder auf eine andere implementierungsdefinierte Weise.
Wenn sie deklariert sind, müssen die Parameter der Hauptfunktion die folgenden Einschränkungen erfüllen:
- Der Wert von
argc
ist nicht negativ.
argv[argc]
soll ein Nullzeiger sein.
- Wenn der Wert von
argc
größer als Null ist, müssen die Array-Mitglieder argv[0]
bis
argv[argc-1]
einschließlich Zeiger auf Zeichenfolgen enthalten, die vor dem Programmstart von der Host-Umgebung implementierungsdefinierte Werte erhalten. Die Absicht besteht darin, dem Programm Informationen zu liefern, die vor dem Programmstart von einer anderen Stelle in der gehosteten Umgebung ermittelt wurden. Wenn die Host-Umgebung nicht in der Lage ist, Zeichenfolgen mit Buchstaben in Groß- und Kleinbuchstaben zu versehen, muss die Implementierung sicherstellen, dass die Zeichenfolgen in Kleinbuchstaben empfangen werden.
- Wenn der Wert von
argc
größer als Null ist, argv[0]
repräsentiert die Zeichenfolge, auf die durch zeigt , den Programmnamen. argv[0][0]
muss das Nullzeichen sein, wenn der Programmname in der Hostumgebung nicht verfügbar ist. Wenn der Wert von argc
größer als eins ist,
repräsentieren die Zeichenfolgen, auf die durch gezeigt argv[1]
wird argv[argc-1]
, die Programmparameter.
- Die Parameter
argc
und argv
und die Zeichenfolgen, auf die das argv
Array zeigt, müssen vom Programm geändert werden können und ihre zuletzt gespeicherten Werte zwischen Programmstart und Programmbeendigung beibehalten.
10) Somit int
kann durch einen Typedef-Namen ersetzt werden, der als definiert ist int
, oder der Typ von argv
kann geschrieben werden als
char **argv
und so weiter.
Programmbeendigung in C99 oder C11
Der von zurückgegebene Wert main()
wird implementierungsdefiniert an die 'Umgebung' übertragen.
5.1.2.2.3 Programmbeendigung
1 Wenn der Rückgabetyp der main
Funktion mit einem kompatiblen Typ kompatibel ist int
, entspricht eine Rückgabe vom ersten Aufruf der main
Funktion dem Aufrufen der exit
Funktion mit dem von der main
Funktion als Argument zurückgegebenen Wert . 11) Wenn Sie das erreichen, das }
die main
Funktion beendet, wird der
Wert 0 zurückgegeben. Wenn der Rückgabetyp nicht kompatibel ist int
, ist der an die Hostumgebung zurückgegebene Beendigungsstatus nicht angegeben.
11) Gemäß 6.2.4 ist die Lebensdauer von Objekten mit der angegebenen automatischen Lagerdauer main
im ersteren Fall abgelaufen, auch wenn sie im letzteren Fall nicht vorhanden wären.
Beachten Sie, dass dies 0
als "Erfolg" vorgeschrieben ist. Sie können EXIT_FAILURE
und EXIT_SUCCESS
von verwenden, <stdlib.h>
wenn Sie es vorziehen, aber 0 ist gut etabliert, ebenso wie 1. Siehe auch Exit-Codes größer als 255 - möglich? .
In C89 (und damit in Microsoft C) gibt es keine Aussage darüber, was passiert, wenn die main()
Funktion zurückgibt, aber keinen Rückgabewert angibt. es führt daher zu undefiniertem Verhalten.
7.22.4.4 Die exit
Funktion
¶5 Schließlich wird die Steuerung an die Hostumgebung zurückgegeben. Wenn der Wert von status
Null ist oder EXIT_SUCCESS
, wird eine implementierungsdefinierte Form des Status erfolgreiche Beendigung zurückgegeben. Wenn der Wert von status
ist EXIT_FAILURE
, 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) lautet:
3.6.1 Hauptfunktion [basic.start.main]
¶1 Ein Programm muss eine globale Funktion namens main enthalten, die den festgelegten Start des Programms darstellt. [...]
¶2 Eine Implementierung darf die Hauptfunktion nicht vordefinieren. Diese Funktion darf nicht überlastet werden. Es muss einen Rückgabetyp vom Typ int haben, ansonsten ist sein Typ implementierungsdefiniert. Alle Implementierungen müssen beide der folgenden Definitionen von main zulassen:
int main() { /* ... */ }
und
int main(int argc, char* argv[]) { /* ... */ }
In letzterer Form argc
ist die Anzahl der Argumente anzugeben, die aus der Umgebung, in der das Programm ausgeführt wird, an das Programm übergeben werden. Wenn argc
ungleich null ist sind diese Argumente geliefert werden argv[0]
durch argv[argc-1]
den Anfangsbuchstaben von nullterminierten Multibyte Strings (NTMBSs) (17.5.2.1.4.2) als Zeiger und argv[0]
wird der Zeiger auf den ursprünglichen Charakter eines NTMBS sein, der den Namen verwendet wird, stellt an Rufen Sie das Programm auf oder ""
. Der Wert von argc
darf nicht negativ sein. Der Wert von argv[argc]
muss 0 sein. [Hinweis: Es wird empfohlen, danach weitere (optionale) Parameter hinzuzufügen argv
. - Endnote]
¶3 Die Funktion main
darf nicht innerhalb eines Programms verwendet werden. Die Verknüpfung (3.5) von main
ist implementierungsdefiniert. [...]
¶5 Eine return-Anweisung in main bewirkt, dass die main-Funktion verlassen wird (Objekte mit automatischer Speicherdauer werden zerstört) und std::exit
der return-Wert als Argument aufgerufen wird . Wenn die Steuerung das Ende von main erreicht, ohne auf eine return-Anweisung zu stoßen, bewirkt dies die Ausführung
return 0;
Der C ++ - Standard sagt ausdrücklich "Es [die Hauptfunktion] soll einen Rückgabetyp haben int
, aber ansonsten ist sein Typ implementierungsdefiniert" und erfordert, dass dieselben zwei Signaturen wie der C-Standard als Optionen unterstützt werden. Ein 'void main ()' ist vom C ++ - Standard direkt nicht zulässig, obwohl es nichts tun kann, um eine nicht standardmäßige Implementierung zu stoppen, die Alternativen zulässt. Beachten Sie, dass C ++ dem Benutzer das Aufrufen verbietet main
(der C-Standard jedoch nicht).
Es gibt einen Absatz von §18.5 Start und Beendigung im C ++ 11-Standard, der mit dem Absatz aus §7.22.4.4 identisch ist. Die exit
Funktion im C11-Standard (oben zitiert), abgesehen von einer Fußnote (die dies einfach dokumentiert EXIT_SUCCESS
und EXIT_FAILURE
definiert ist in <cstdlib>
).
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 (möglicherweise leer) hat. Wenn Sie dies nicht verwenden, können Sie trotzdem über ' extern char **environ;
' in die Umgebung gelangen . Diese globale Variable ist unter denen in POSIX insofern einzigartig, als sie keinen Header hat, der sie deklariert.
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 char
verweist, von denen jeder auf eine Zeichenfolge verweist, die Informationen über die Umgebung für diese Ausführung des Programms bereitstellt (5.1). 2.2.1).
Microsoft C.
Der Microsoft VS 2010- 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 void
return deklariert werden (kein Rückgabewert). Wenn Sie void main
oder wmain
als ungültig deklarieren , können Sie keinen Exit-Code mithilfe einer return-Anweisung an den übergeordneten Prozess oder das übergeordnete Betriebssystem zurückgeben. Um einen Exit-Code zurückzugeben, wenn main
oder wmain
als deklariert ist void
, müssen Sie die exit
Funktion verwenden.
Mir ist nicht klar, was passiert (welcher Exit-Code wird an das übergeordnete oder Betriebssystem zurückgegeben), wenn ein Programm mit beendet void main()
wird - und die MS-Website ist ebenfalls still.
Interessanterweise schreibt MS nicht die Version mit zwei Argumenten vor main()
, die die C- und C ++ - Standards erfordern. Es wird nur eine Form mit drei Argumenten vorgeschrieben, wobei das dritte Argument char **envp
ein Zeiger auf eine Liste von Umgebungsvariablen ist.
Auf der Microsoft-Seite werden auch einige andere Alternativen aufgeführt, für wmain()
die breite Zeichenfolgen erforderlich sind, und einige weitere.
Die Microsoft Visual Studio 2005- Version dieser Seite wird nicht void main()
als Alternative aufgeführt. Die Versionen ab Microsoft Visual Studio 2008 tun dies.
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 aufgerufen werden, main
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 erfolgt der Programmstart, 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 des C-Programms ohne Nutzen eines Betriebssystems erfolgen kann) sind Name und Typ der beim Programmstart aufgerufenen Funktion implementierungsdefiniert. Alle Bibliothekseinrichtungen, die einem freistehenden Programm zur Verfügung stehen, mit Ausnahme der in Abschnitt 4 geforderten Mindestmenge, sind implementierungsdefiniert.
Der Effekt der Programmbeendigung in einer freistehenden Umgebung ist implementierungsdefiniert.
Der Querverweis auf Klausel 4 Konformität bezieht sich auf Folgendes:
¶5 Ein streng konformes Programm darf nur die Merkmale der in dieser Internationalen Norm angegebenen Sprache und Bibliothek verwenden. 3) Es darf keine Ausgabe erzeugen, die von einem nicht spezifizierten, undefinierten oder implementierungsdefinierten Verhalten abhängt, und darf keine Mindestimplementierungsgrenze überschreiten.
¶6 Die beiden Formen der konformen Implementierung sind gehostet und freistehend . Eine konform gehostete Implementierung akzeptiert streng konforme Programme. Eine konforme freistehende Ausführung ist jedes streng konformes Programm akzeptieren , in dem die Nutzung der Funktionen in der Bibliothek Klausel (Ziffer 7) spezifizierten den Inhalt der Standard - Header eingeschlossen ist <float.h>
, <iso646.h>
, <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 sie das Verhalten eines streng konformen Programms nicht ändern. 4)
¶7 Ein konformes Programm ist für eine konforme Implementierung akzeptabel. 5)
3) Ein streng konformes Programm kann bedingte Funktionen verwenden (siehe 6.10.8.3), vorausgesetzt, die Verwendung wird durch eine geeignete Vorverarbeitungsrichtlinie für bedingte Einbeziehung unter Verwendung des zugehörigen Makros geschützt. Zum Beispiel:
#ifdef __STDC_IEC_559__ /* FE_UPWARD defined */
/* ... */
fesetround(FE_UPWARD);
/* ... */
#endif
4) Dies bedeutet, dass eine konforme Implementierung keine anderen Kennungen als die in dieser Internationalen Norm ausdrücklich reservierten reserviert.
5) Streng konforme Programme sollen unter konformen Implementierungen maximal portierbar sein. Konforme Programme können von nicht portierbaren Funktionen einer konformen Implementierung abhängen.
Es fällt auf, dass der einzige Header, der für eine freistehende Umgebung erforderlich ist, die tatsächlich Funktionen definiert, <stdarg.h>
(und selbst diese können und sind oft nur Makros) sind.
Standard C ++ - Freistehende Umgebung
So wie der C-Standard sowohl gehostete als auch freistehende Umgebungen erkennt, erkennt auch der C ++ - Standard dies. (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 dieser Internationale Standard den Satz verfügbarer Bibliotheken. Eine freistehende Implementierung ist eine Implementierung, bei der die Ausführung ohne den Vorteil eines Betriebssystems erfolgen kann, und verfügt über einen implementierungsdefinierten Satz von Bibliotheken, der bestimmte Sprachunterstützungsbibliotheken enthält (17.6.1.3).
¶8 Eine konforme Implementierung kann Erweiterungen (einschließlich zusätzlicher Bibliotheksfunktionen) aufweisen, sofern sie das Verhalten eines wohlgeformten Programms nicht ändern. Implementierungen sind erforderlich, um Programme zu diagnostizieren, die solche Erweiterungen verwenden, die gemäß dieser internationalen Norm schlecht ausgebildet sind. Danach können sie jedoch solche Programme kompilieren und ausführen.
¶9 Jede Implementierung muss eine Dokumentation enthalten, die alle bedingt unterstützten Konstrukte identifiziert, die nicht unterstützt werden, 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 dieser Internationale Standard den Satz verfügbarer Header.
Eine freistehende Implementierung verfügt über einen implementierungsdefinierten Satz von Headern. Dieser Satz muss mindestens die in Tabelle 16 aufgeführten Überschriften enthalten.
Die mitgelieferte Version des Headers <cstdlib>
muss mindestens die Funktionen erklären abort
, atexit
, at_quick_exit
, exit
, und quick_exit
(18,5). Die anderen in dieser Tabelle aufgeführten Header müssen dieselben 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 int main()
in C?
Die Norm §5.1.2.2.1 der Norm C11 zeigt die bevorzugte Notation - int main(void)
- aber es gibt auch zwei Beispiele in der Norm, die zeigen int main()
: §6.5.3.4 ¶8 und §6.7.6.3 ¶20 . Nun ist es wichtig anzumerken, dass Beispiele nicht „normativ“ sind. Sie sind nur zur Veranschaulichung. Wenn die Beispiele Fehler enthalten, wirken sie sich nicht direkt auf den Haupttext des Standards aus. Das heißt, sie weisen stark auf das erwartete Verhalten hin. Wenn der Standard also int main()
ein Beispiel enthält, deutet dies darauf hin, dass dies int main()
nicht verboten ist, auch wenn es nicht die bevorzugte Notation ist.
6.5.3.4 Die sizeof
und _Alignof
Operatoren
…
¶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;
}