main 関数とコマンド ライン引数

すべての C++ プログラムは、main 関数を持つ必要があります。 main 関数を使用せずに C++ プログラムをコンパイルしようとすると、コンパイラでエラーが発生します (ダイナミック リンク ライブラリと static ライブラリには main 関数がありません。関数は main ソース コードの実行を開始する場所ですが、プログラムが関数に入る main 前に、明示的な初期化子を持たないすべての static クラス メンバーは 0 に設定されます。 Microsoft C++ では、グローバルな static オブジェクトも main に入る前に初期化されます。 他の C++ の関数には適用されない複数の制限が main 関数に適用されます。 main 関数は、次のことを行います。

  • オーバーロードすることはできません (「関数のオーバーロード」を参照してください)。
  • inline として宣言することはできません。
  • static として宣言することはできません。
  • そのアドレスを取得することはできません。
  • プログラムから呼び出すことはできません。

main 関数シグネチャ

main 関数は、言語に組み込まれているため、宣言を持ちません。 これが行われた場合、main の宣言構文は次のようになります。

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

main に戻り値が指定されていない場合、コンパイラは戻り値として 0 を指定します。

標準コマンドライン引数

main の引数を使用すると、コマンドラインで引数を簡単に解析できます。 argcargv の型は、言語によって定義されています。 argc および argv という名前は従来と同じですが、自由に名前を付けることができます。

引数の定義は、次のとおりです。

argc
これに続いて argv で渡される引数の数を格納した整数。 argc パラメーターは、必ず 1 以上になります。

argv
プログラムのユーザーが入力したコマンド ライン引数を表す、null で終了する文字列配列。 慣例により、argv[0] は、プログラムが起動されるコマンドです。 argv[1] は、最初のコマンド ライン引数です。 コマンドラインからの最後の引数は argv[argc - 1] であり、argv[argc] は常に NULL です。

コマンドライン処理を抑制する方法の詳細については、「C++ コマンドライン処理のカスタマイズ」を参照してください。

Note

規則により、argv[0] はプログラムのファイル名です。 ただし、Windows では、CreateProcess を使用してプロセスを生成することができます。 1 番目と 2 番目の引数 (lpApplicationNamelpCommandLine) の両方を使用する場合は、argv[0] を実行可能ファイルの名前にすることはできません。 GetModuleFileName を使用すると、実行可能ファイル名とその完全修飾パスを取得できます。

Microsoft 固有の拡張機能

以下のセクションでは、Microsoft 固有の動作について説明します。

wmain 関数と _tmain マクロ

Unicode ワイド文字を使用するようにソース コードを設計する場合は、Microsoft 固有の wmain エントリ ポイントを使用できます。これは、main のワイド文字バージョンです。charchar 次に、wmain の有効な宣言構文を示します。

int wmain();
int wmain(int argc, wchar_t *argv[]);

tchar.h」で定義されているプリプロセッサ マクロである、Microsoft 固有の _tmain を使用することもできます。 _UNICODE が定義されていない場合、_tmainmain に解決されます。 定義されている場合、_tmainwmain に解決されます。 _t で始まる _tmain マクロとその他のマクロは、ナローとワイドの両方の文字セットに個別のバージョンを構築する必要があるコードに便利です。char 詳細については、「汎用テキスト マップの使用」を参照してください。

main から void を返す

Microsoft 拡張機能として、main および wmain 関数を void を返す (戻り値なし) ように宣言できます。 この拡張機能は、他のいくつかのコンパイラでも使用できますが、その使用は推奨されていません。 main が値を返さない場合、対称性のために使用できます。

void を返すように main または wmain を宣言した場合、return ステートメントを使用して親プロセスまたはオペレーティング システムに exit コードを返すことはできません。 main または wmainvoid として宣言されているときに exit コードを返すには、exit 関数を使用する必要があります。

envp コマンド ライン引数

main または wmain シグネチャにより、オプションの Microsoft 固有の拡張機能を使用して環境変数にアクセスできます。 この拡張機能は、Windows および UNIX システム用の他のコンパイラでも共通しています。 名前 envp は従来と同じですが、環境パラメーターに任意の名前を付けることができます。 環境パラメーターを含む引数リストの有効な宣言を次に示します。

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

envp
オプションの envp パラメーターは、ユーザーの環境で設定された変数を表す文字列の配列です。 この配列は NULL エントリで終了します。 これは、char (char *envp[]) へのポインターの配列として、または char (char **envp) へのポインターへのポインターとして宣言できます。 プログラムが main ではなく wmain を使用している場合は、char の代わりに wchar_t データ型を使用します。

main および wmain に渡される環境ブロックは、現在の環境の "固定の" コピーです。 その後 putenv または _wputenv の呼び出しによって環境を変更する場合、現在の環境 (getenv または _wgetenv および _environ または _wenviron 変数が返す) は変わりますが、envp が指すブロックは変わりません。 環境処理を抑制する方法の詳細については、「C++ コマンドライン処理のカスタマイズ」を参照してください。 envp 引数は、C89 標準と互換性がありますが、C++ 標準には対応していません。

main への引数の例

次の例は、main への argcargv、および envp 引数の使用方法を示しています。

// 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";
    }
}

C++ のコマンド ライン引数の解析

Microsoft C/C++ コードによって使用されるコマンドライン解析ルールは、Microsoft 固有のものです。 ランタイム スタートアップ コードは、オペレーティング システムのコマンド ラインで指定された引数を解釈する場合に、次のルールを使用します。

  • 引数は、空白 (スペースまたはタブ) で区切ります。

  • 最初の引数 (argv[0]) は、特別に処理されます。 それはプログラム名を表します。 有効なパス名である必要があるため、一部分を二重引用符 ( " ) で囲むことが許可されます。 二重引用符は、argv[0] の出力には含まれません。 二重引用符で囲まれた部分については、スペース文字またはタブ文字が引数の末尾として解釈されません。char この一覧で後に示す規則は適用されません。

  • 二重引用符で囲まれた文字列は、空白文字が含まれているかどうかにかかわらず、1 つの引数として解釈されます。char 二重引用符で囲んだ文字列を引数に埋め込むこともできます。 キャレット (^) は、エスケープ文字または区切り記号として認識されません。char 引用符で囲まれた文字列内では、二重引用符のペアは単一のエスケープされた二重引用符として解釈されます。 終了の二重引用符が検出される前にコマンド ラインが終了した場合は、それまでに読み取られたすべての文字が最後の引数として出力されます。char

  • 円記号を前に付けた二重引用符 ( \" ) は、リテラルの二重引用符文字 ( " ) として解釈されます。

  • 二重引用符の直前にある円記号以外は、円記号として文字どおり解釈されます。

  • 二重引用符の直前に円記号が偶数個あると、円記号のペア ( \\ ) ごとに 1 個の円記号 ( \ ) が argv 配列に配置されます。この場合、二重引用符 ( " ) は文字列の区切り記号として解釈されます。

  • 奇数個の円記号の後に二重引用符がある場合は、円記号のペア ( \\ ) ごとに 1 個の円記号 ( \ ) が argv 配列に配置されます。 二重引用符は残りのバックスラッシュによってエスケープ シーケンスとして解釈され、リテラルの二重引用符 (") が argv に配置されます。main

コマンドライン引数の解析の例

次のプログラムは、コマンド ライン引数がどのように受け渡されるかを示します。

// 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";
}

コマンド ラインの解析結果

次の表は、前の一覧の規則を示しながら、入力例と予想される出力を示しています。

コマンド ライン入力 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

ワイルドカードの展開

Microsoft コンパイラでは、必要に応じて、コマンド ラインでファイル名とパスの引数を指定するときに、ワイルドカード文字、疑問符 (?)、およびアスタリスク (*) を使用できます。char

コマンドライン引数は、ランタイム スタートアップ コードの内部ルーチンによって処理されます。既定では、ワイルドカードは argv 文字列配列内の個別の文字列に展開されません。 /link コンパイラ オプションまたは LINK コマンド ラインで setargv.obj ファイル (wmain の場合は wsetargv.obj ファイル) を含めることで、ワイルドカードの展開を有効にすることができます。

ランタイムのスタートアップ リンカー オプションの詳細については、「リンク オプション」を参照してください。

C++ のコマンド ライン処理のカスタマイズ

プログラムがコマンド ライン引数を受け取らない場合は、コマンド ライン処理ルーチンを抑制して領域を少し節約できます。 その使用を抑制するには、 noarg.obj ファイルを (mainwmain どちらの場合でも) /link コンパイラ オプションまたは LINK コマンド ラインに含めます。

同様に、 envp 引数を使用して環境のテーブルにアクセスしない場合は、内部の環境処理ルーチンを抑制できます。 その使用を抑制するには、 noenv.obj ファイルを (mainwmain どちらの場合でも) /link コンパイラ オプションまたは LINK コマンド ラインに含めます。

プログラムによって、C ランタイム ライブラリの spawn または exec ファミリのルーチンが呼び出されることがあります。 その場合は、親プロセスから子プロセスに環境を渡すために環境処理ルーチンが使用されるため、抑制しないでください。

関連項目

基本的な概念