Freigeben über


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 voiddeklariert 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, argvund 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 von argv[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 ( \ ) im argv-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 ( \ ) im argv-Array platziert. Das doppelte Anführungszeichen wird durch den verbleibenden umgekehrten Schrägstrich als Escapesequenz interpretiert, sodass ein tatsächliches doppeltes Anführungszeichen ( " ) in argv 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.

Siehe auch

Basic concepts (Grundlegende Konzepte)