C++の基礎: main関数について学ぶ
main関数は、C++で記述されたアプリケーションの主要部分であり、オペレーティングシステム(Windows、iOS、Mac-OS、Android、Linuxなど)で実行されるプログラムへの指定されたエントリポイントです。すべてのC++アプリケーションプログラムには、すべてのアプリケーション文や関数を開始するためのmain関数が1つ存在します。main関数を持たないライブラリ、ダイナミックライブラリ、スタティックライブラリなどのC++ファイルを作成し、メインのC++ファイルに追加されたサブのC++ファイルとして使用することはできますが、アプリケーションを実行するためには、必ずmain関数が必要です。
一部のCおよびC ++コンパイラでは、以下のようにmain()関数をパラメータ無し、戻り値無しで使用できるものがあります。
main()
{
// main program here
}
一般的にmain()関数は、プログラムが正常に終了したことを示す整数値を返します。これは、アプリケーションやコードが問題なく動作しているか、クラッシュしていないかを確認するために必要です。この戻り値により、他のアプリケーションで他の関数を安全に使用することができます。アプリケーション実行時に問題を捕捉し、main関数のreturn文を呼ばずにメインの実行が正常に終了した場合、コンパイラはその関数が暗黙のreturn文で終了したと見なします。
以下のコードは、パラメータを持たない最も一般的なmain()関数の例です。
int main()
{
// main program here
return 0;
}
ここでの戻り値は、アプリケーションが正常に実行されて終了したことを表すEXIT_SUCCESS、またはアプリケーションが失敗したことを表すEXIT_FAILUREとなりますが、成功した場合の戻り値として0も使用されます(EXIT_SUCCESSと同じ)。一般的にはreturn 0;を使用しますが、以下の表のように説明できます。
説明 | 戻り値 |
---|---|
アプリケーションが正常に動作して終了 | 0 |
アプリケーションが正常に動作して終了(<cstdlib>ヘッダーで定義) | EXIT_SUCCESS |
アプリケーションが失敗(<cstdlib>ヘッダーで定義) | EXIT_FAILURE |
main()関数が暗黙的または明示的にゼロを返した場合、オペレーティングシステムはプログラムが正常に終了したと解釈します。他の関数の戻り値をmainの戻り値の最後に使用することができ、オペレーティングシステムによってはその値へのアクセスを何らかの方法で呼び出し元に与えることができますが、これは必須ではなく、またシステムプラットフォーム間での移植性もありません。
一般的にmain関数は、2つのパラメータ(argcとargv)を引数として使用します。これらのパラメータを使用すると、実行環境(オペレーティングシステム)から任意のマルチバイト文字列を渡すことができます。
一般的なmain関数は、引数を使用して以下のように使用されます。
int main (int argc, char *argv[])
{
// main program here
return 0;
}
各パラメータの説明は以下の通りです。
- argcは引数の数であり、オペレーティングシステム環境からプログラムに渡される引数の数を表す正の整数値です。 argc > 0の場合は、argv[]にパラメータが定義されています。
- argv[]は、実行時にプログラムに渡される引数を表すマルチバイト配列である。 argv[0]は、nullポインタではなく、プログラムの起動に使用された名前を表す文字列、または空の文字列を指しています。このパラメータは文字列であり、std::strtok を使用してトークンで区切ることができます。argvが指す配列の要素数は argc+1であり、最後の要素 ( argv[argc] ) は null ポインタであることが保証されています。
C++Builderでは、main()関数は以下のように定義されています。
int _tmain(int argc, _TCHAR* argv[])
{
return 0;
}
一般的にmain()関数は
- メインプログラムであるため、サブプログラム内で使用することができず、再帰的に呼び出されることもありません。
- return文を含む必要はなく、アプリケーション制御がmain()の最後に到達してもreturn文に到達しなければ0を返します。
- アドレスは使用できません。
- main関数は事前に定義することも、オーバーロードすることもできません。
- auto を戻り値の型として使用するなど、main関数の戻り値の型を推測することはできません(C++14 以降)
- C言語リンケージで削除または宣言されたものとして定義することはできません(C++ 17以降)
- returnの実行(または main の終わりに到達したときの暗黙の return)は、まず関数を通常通り終了し(自動保存期間を持つオブジェクトを破棄する)、次に returnの引数と同じ引数で std::exitを呼び出すことと同じです。( std::exitは静的オブジェクトを破壊し、プログラムを終了させます)。
ここでは、さまざまな空のC++アプリケーションにおけるmain()関数の例をご紹介します。
一般的なC++コード:
#include <iostream>
int main (int argc, char *argv[])
{
// main program here
return 0;
}
C++Builderの空のコンソールアプリケーション:
#pragma hdrstop
#pragma argsused
#include <stdio.h>
#ifdef _WIN32
#include <tchar.h>
#else
typedef char _TCHAR;
#define _tmain main
#endif
int _tmain(int argc, _TCHAR* argv[])
{
return 0;
}
C++Builderの空のVCLアプリケーション:
#include <vcl.h>
#include <windows.h>
#pragma hdrstop
#pragma argsused
#include <tchar.h>
#include <stdio.h>
int _tmain(int argc, _TCHAR* argv[])
{
return 0;
}
C++Builderの空のFMXアプリケーション:
#include <fmx.h>
#pragma hdrstop
#pragma argsused
#ifdef _WIN32
#include <tchar.h>
#else
typedef char _TCHAR;
#define _tmain main
#endif
#include <stdio.h>
int _tmain(int argc, _TCHAR* argv[])
{
return 0;
}
C++Builderの(フォームユニットとGUIを持った)空のVCLアプリケーション (Project1.cppの例):
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include <tchar.h>
//---------------------------------------------------------------------------
USEFORM("Unit1.cpp", Form1);
//---------------------------------------------------------------------------
int WINAPI _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int)
{
try
{
Application->Initialize();
Application->MainFormOnTaskBar = true;
Application->CreateForm(__classid(TForm1), &Form1);
Application->Run();
}
catch (Exception &exception)
{
Application->ShowException(&exception);
}
catch (...)
{
try
{
throw Exception("");
}
catch (Exception &exception)
{
Application->ShowException(&exception);
}
}
return 0;
}
//---------------------------------------------------------------------------
C++ Builder (フォームユニットとGUIを持った)FMXのマルチデバイスアプリケーション(Project1.cppの例):
//---------------------------------------------------------------------------
#include <fmx.h>
#ifdef _WIN32
#include <tchar.h>
#endif
#pragma hdrstop
#include <System.StartUpCopy.hpp>
//---------------------------------------------------------------------------
USEFORM("Unit1.cpp", Form1);
//---------------------------------------------------------------------------
extern "C" int FMXmain()
{
try
{
Application->Initialize();
Application->CreateForm(__classid(TForm1), &Form1);
Application->Run();
}
catch (Exception &exception)
{
Application->ShowException(&exception);
}
catch (...)
{
try
{
throw Exception("");
}
catch (Exception &exception)
{
Application->ShowException(&exception);
}
}
return 0;
}
//---------------------------------------------------------------------------