main
-Funktion und Befehlszeilenargumente
Alle C++-Programme müssen über eine main
-Funktion verfügen. Wenn Sie versuchen, ein C++-Programm ohne main
-Funktion zu kompilieren, löst der Compiler einen Fehler aus. (Dynamic Link Libraries und static-Bibliotheken verfügen nicht über eine main
-Funktion.) Die Ausführung des Quellcodes beginnt in der main
-Funktion. Bevor ein Programm jedoch in die main
-Funktion eintritt, werden alle Member der static-Klasse ohne explizite Initialisierer auf null festgelegt. In Microsoft C++ werden globale static-Objekte ebenfalls vor dem Eintritt in main
initialisiert. Für die main
-Funktion gelten mehrere Einschränkungen, die für andere C++-Funktionen nicht gelten. Mit der Funktion main
werden folgende Aktionen ausgeführt:
- Kann nicht überladen werden (siehe Funktionsüberladung).
- Sie kann nicht als
inline
deklariert werden. - Sie kann nicht als
static
deklariert werden. - Ihre Adresse kann nicht übernommen werden.
- Sie kann nicht aus Ihrem Programm aufgerufen werden.
Die Signatur der main
-Funktion
Die main
-Funktion muss nicht deklariert werden, da sie in die Sprache integriert ist. Wäre eine Deklaration erforderlich, würde die Deklarationssyntax für main
wie folgt aussehen:
int main();
int main(int argc, char *argv[]);
Wenn in main
kein Rückgabewert angegeben ist, stellt der Compiler den Rückgabewert null bereit.
Standardmäßige Befehlszeilenargumente
Die Argumente für main
bieten eine bequeme Möglichkeit, Argumente in der Befehlszeile zu analysieren. Die Typen für argc
und argv
werden von der Programmiersprache definiert. Die Namen argc
und argv
werden üblicherweise verwendet, Sie können jedoch beliebige Namen vergeben.
Die Argumentdefinitionen sind wie folgt:
argc
Eine Ganzzahl, die die Anzahl der Argumente enthält, die in argv folgen. Der argc-Parameter ist immer größer als oder gleich 1.
argv
Ein Array von Zeigern auf Zeichenfolgen, die auf NULL enden und von den Benutzern des Programms eingegebene Befehlszeilenargumente darstellen. Gemäß der Konvention ist argv[0]
der Befehl, mit dem das Programm aufgerufen wird. argv[1]
ist das erste Befehlszeilenargument. Das letzte Argument in der Befehlszeile ist argv[argc - 1]
, und argv[argc]
ist immer NULL.
Informationen zum Unterdrücken der Befehlszeilenverarbeitung finden Sie unter Anpassen der C++-Befehlszeilenverarbeitung.
Hinweis
argv[0]
ist gemäß Konvention der Dateiname des Programms. Unter Windows ist es jedoch möglich, einen Prozess mithilfe von CreateProcess
zu erzeugen. Wenn Sie sowohl das erste als auch das zweite Argument (lpApplicationName
und lpCommandLine
) verwenden, entspricht argv[0]
möglicherweise nicht dem Namen der ausführbaren Datei. Sie können GetModuleFileName
verwenden, um den Namen der ausführbaren Datei und ihren vollqualifizierten Pfad abzurufen.
Microsoft-spezifische Erweiterungen
In den folgenden Abschnitten werden Verhaltensweisen beschrieben, die für Microsoft spezifisch sind.
Die wmain
-Funktion und das _tmain
-Makro
Wenn Sie Ihren Quellcode für die Verwendung von Unicode-Breitzeichen entwerfen, können Sie den Microsoft-spezifischen wmain
Einstiegspunkt verwenden, d. h. die Breitzeichenversion von main
. Im Folgenden die effektive Deklarationssyntax für wmain
:
int wmain();
int wmain(int argc, wchar_t *argv[]);
Sie können auch das Microsoft-spezifische _tmain
-Makro verwenden, bei dem es sich um ein Präprozessormakro handelt, das in tchar.h
definiert ist. _tmain
wird zu main
aufgelöst, sofern nicht _UNICODE
definiert ist. In diesem Fall wird _tmain
in wmain
aufgelöst. Das _tmain
-Makro und andere Makros, die mit _t
beginnen, sind hilfreich für Code, durch den separate Zeichensatzversionen sowohl mit schmalen als auch mit breiten Zeichen erstellt werden müssen. Weitere Informationen finden Sie unter Verwendung von generischen Textzuordnungen.
Zurückgeben von void
von main
Als Microsoft-Erweiterung kann die main
-Funktion und die wmain
-Funktion so deklariert werden, dass void
zurückgegeben wird (kein Rückgabewert). Diese Erweiterung ist auch in einigen anderen Compilern verfügbar, von ihrer Verwendung wird jedoch abgeraten. Sie ist zu Zwecken der Symmetrie verfügbar, wenn main
keinen Wert zurückgibt.
Wenn Sie main
oder wmain
für die Rückgabe von void
deklarieren, können Sie keine return
-Anweisung verwenden, um exit-Code an den übergeordneten Prozess oder das Betriebssystem zurückzugeben. Um exit-Code zurückzugeben, wenn main
oder wmain
als void
deklariert ist, müssen Sie die exit
-Funktion verwenden.
envp
-Befehlszeilenargument
Die Signaturen main
oder wmain
unterstützen eine optionale Microsoft-spezifische Erweiterung für den Zugriff auf Umgebungsvariablen. Diese Erweiterung ist auch in anderen Compilern für Windows- und UNIX-Systeme weit verbreitet. Der Name envp
wird üblicherweise verwendet, Sie können dem Umgebungsparameter jedoch einen beliebigen Namen geben. Im Folgenden die effektiven Deklarationen für die Argumentlisten, die den Umgebungsparameter enthalten:
int main(int argc, char* argv[], char* envp[]);
int wmain(int argc, wchar_t* argv[], wchar_t* envp[]);
envp
Der optionale envp
-Parameter ist ein Zeichenfolgenarray, das die Variablen darstellt, die in der Benutzerumgebung festgelegt werden. Das Array wird mit einem NULL-Eintrag beendet. Er kann als Array von Zeigern auf char
(char *envp[]
) oder als Zeiger auf Zeiger auf char
(char **envp
) deklariert werden. Wenn Ihr Programm wmain
anstelle von main
verwendet, sollten Sie den Datentyp wchar_t
anstelle von char
verwenden.
Der Umgebungsblock, der an main
und wmain
übergeben wird, ist eine „eingefrorene“ Kopie der aktuellen Umgebung. Wenn Sie die Umgebung später durch einen Aufruf von putenv
oder _wputenv
ändern, ändert sich die aktuelle Umgebung (die von getenv
oder _wgetenv
und den Variablen _environ
oder _wenviron
zurückgegeben wird). Der Block, auf den von envp
gezeigt wird, ändert sich jedoch nicht. Weitere Informationen zum Unterdrücken der Umgebungsverarbeitung finden Sie unter Anpassen der C++-Befehlszeilenverarbeitung. Das envp
-Argument ist mit dem C89-Standard kompatibel, aber nicht mit C++-Standards.
Beispielargumente für main
Im folgenden Beispiel wird gezeigt, wie die Argumente argc
, argv
und envp
für main
verwendet werden:
// argument_definitions.cpp
// compile with: /EHsc
#include <iostream>
#include <string.h>
using namespace std;
int main( int argc, char *argv[], char *envp[] )
{
bool numberLines = false; // Default is no line numbers.
// If /n is passed to the .exe, display numbered listing
// of environment variables.
if ( (argc == 2) && _stricmp( argv[1], "/n" ) == 0 )
numberLines = true;
// Walk through list of strings until a NULL is encountered.
for ( int i = 0; envp[i] != NULL; ++i )
{
if ( numberLines )
cout << i << ": "; // Prefix with numbers if /n specified
cout << envp[i] << "\n";
}
}
Analysieren von C++-Befehlszeilenargumenten
Die von C/C++-Code von Microsoft verwendeten Regeln für die Befehlszeilenanalyse sind spezifisch für Microsoft. Beim Interpretieren von Argumenten, die in der Befehlszeile des Betriebssystems angegeben werden, verwendet der Startcode der Laufzeit die folgenden Regeln:
Argumente werden durch einen Leerraum (Leerzeichen oder Tabstopp) abgegrenzt.
Das erste Argument (
argv[0]
) wird besonders behandelt. Es repräsentiert den Programmnamen. Da es sich um einen gültigen Pfadnamen handeln muss, sind Bestandteile in doppelten geraden Anführungszeichen oben ("
) zulässig. Die Anführungszeichen sind nicht in der Ausgabe vonargv[0]
enthalten. Die Anführungszeichen verhindern, dass bei den darin eingeschlossenen Bestandteilen Leerzeichen oder Tabstoppzeichen als Ende des Arguments interpretiert werden. Die weiter unten in dieser Liste aufgeführten Regeln gelten nicht.Eine Zeichenkette, die von doppelten Anführungszeichen umgeben ist, wird als ein einziges Argument interpretiert, das Leerzeichen enthalten kann. Eine Zeichenfolge in Anführungszeichen kann in ein Argument eingebettet sein. Die Einfügemarke (
^
) wird nicht als Escape- oder Trennzeichen erkannt. Innerhalb einer in Anführungszeichen eingeschlossenen Zeichenfolge wird ein Paar aus doppelten Anführungszeichen als ein einzelnes doppeltes Anführungszeichen mit Escapezeichen interpretiert. Wenn die Befehlszeile endet, bevor ein schließendes doppeltes Anführungszeichen gefunden wird, werden alle bis dahin gelesenen Zeichen als letztes Argument ausgegeben.Wenn dem doppelten Anführungszeichen ein umgekehrter Schrägstrich (
\"
) vorangestellt ist, wird diese Zeichenfolge als tatsächliches doppeltes Anführungszeichen ("
) interpretiert.Ein umgekehrter Schrägstrich wird als solcher interpretiert, sofern er nicht unmittelbar vor einem Anführungszeichen steht.
Wenn ein doppeltes Anführungszeichen auf eine gerade Anzahl umgekehrter Schrägstriche folgt, wird für jedes Paar umgekehrter Schrägstriche (
\\
) ein umgekehrter Schrägstrich (\
) imargv
-Array platziert. Das doppelte Anführungszeichen ("
) wird als Zeichenfolgentrennzeichen interpretiert.Wenn ein doppeltes Anführungszeichen auf eine ungerade Anzahl umgekehrter Schrägstriche folgt, wird für jedes Paar umgekehrter Schrägstriche (
\\
) ein umgekehrter Schrägstrich (\
) imargv
-Array platziert. Das doppelte Anführungszeichen wird durch den verbleibenden umgekehrten Schrägstrich als Escapesequenz interpretiert, sodass ein tatsächliches doppeltes Anführungszeichen ("
) inargv
platziert wird.
Beispiel für die Analyse von Befehlszeilenargumenten
Das folgende Programm zeigt, wie Befehlszeilenargumente übergeben werden:
// command_line_arguments.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
int main( int argc, // Number of strings in array argv
char *argv[], // Array of command-line argument strings
char *envp[] ) // Array of environment variable strings
{
int count;
// Display each command-line argument.
cout << "\nCommand-line arguments:\n";
for( count = 0; count < argc; count++ )
cout << " argv[" << count << "] "
<< argv[count] << "\n";
}
Ergebnisse der Befehlszeilenanalyse
Die folgende Tabelle zeigt beispielhafte Eingaben und zu erwartende Ausgaben, wobei die Regeln in der vorangehenden Liste aufgezeigt werden.
Befehlszeileneingabe | argv[1] | argv[2] | argv[3] |
---|---|---|---|
"abc" d e |
abc |
d |
e |
a\\b d"e f"g h |
a\\b |
de fg |
h |
a\\\"b c d |
a\"b |
c |
d |
a\\\\"b c" d e |
a\\b c |
d |
e |
a"b"" c d |
ab" c d |
Platzhaltererweiterung
Der Microsoft-Compiler ermöglicht die optionale Verwendung von Platzhalterzeichen (), des Fragezeichens (?
) und Sternchens (*
), um Dateinamen und Pfadargumente in der Befehlszeile anzugeben.
Befehlszeilenargumente werden von einer internen Routine im Startcode der Laufzeit behandelt, der Platzhalterzeichen im argv
-Zeichenfolgenarray standardmäßig nicht in getrennte Zeichenfolgen erweitert. Sie können die Platzhaltererweiterung aktivieren, indem Sie die Datei „setargv.obj
“ (Datei „wsetargv.obj
“ für wmain
) in Ihre /link
-Compileroptionen oder LINK
-Befehlszeile einschließen.
Weitere Informationen zu den Optionen für den Runtimestartlinker finden Sie unter Linkoptionen.
Anpassen der C++-Befehlszeilenverarbeitung
Wenn das Programm keine Befehlszeilenargumente akzeptiert, können Sie die Routine zur Befehlszeilenverarbeitung unterdrücken, um ein wenig Speicherplatz zu sparen. Um ihre Verwendung zu unterdrücken, schließen Sie die noarg.obj
-Datei (sowohl für main
als auch für wmain
) in Ihre /link
-Compileroptionen oder LINK
-Befehlszeile ein.
Ebenso können Sie die interne Routine zur Umgebungsverarbeitung unterdrücken, wenn Sie nie über das envp
-Argument auf die Umgebungstabelle zugreifen. Um ihre Verwendung zu unterdrücken, schließen Sie die noenv.obj
-Datei (sowohl für main
als auch für wmain
) in Ihre /link
-Compileroptionen oder LINK
-Befehlszeile ein.
Das Programm ruft möglicherweise die spawn
- oder exec
-Gruppe von Routinen in der C-Laufzeitbibliothek auf. Wenn dies der Fall ist, sollten Sie die Routine zur Umgebungsverarbeitung nicht unterdrücken, da diese Routine verwendet wird, um eine Umgebung aus dem übergeordneten Prozess an den untergeordneten Prozess zu übergeben.