16.2 エントリポイント

例えば、WindowsのGUIプログラムを記述しようとした時に、以下が最小のプログラムであるというのを見た事はないでしょうか。

#include <windows.h>
int WINAPI WinMain(
HINSTANCE hThisInst,
HINSTANCE hPrevInst,
LPSTR lpszArgs,
int nWinMode
)
{
// ....
}

// main関数がない

WinMainという関数がmain関数の代わりをしているかのように振舞います。

また、SDLというグラフィックハードウェアへのアクセスを提供するライブラリでは、main関数を記述できるかのように思えます。

#include<sdl/sdl.h>
int main(int* argc,char* argv[])
{
// ....
}

sdl.hというヘッダーファイルを辿っていくと、中には以下のような記述があります。

//SDL_main.h
#define main SDL_main
/** The prototype for the application’s main() function */
extern C_LINKAGE int SDL_main(int argc, char *argv[]);

これはつまり、mainと記述した場合、SDL_mainへと置き換わるという事です。よって、SDLライブラリをインクルードした状態でmain関数を記述すると

#include<sdl/sdl.h>
int main(int* argc,char* argv[])
{
// ....
}

以下のように置き換わるのです。

#include<sdl/sdl.h>
int SDL_main(int argc, char *argv[])
{
// ....
}

となると、コードからはmain関数が全くどこにもない事になってしまいました。「2.2 最小のプログラム」で説明したようにプログラムはmain関数から開始されるはずです。これは、何故コンパイルに成功し、main関数の代替のように振る舞えるのでしょうか。 結論から言えば、エントリポイントをコンパイル時に設定する事で任意の関数名からプログラムを開始する事ができるからなのです。エントリポイントとは、開始するプログラムの位置を言います。

例えば前述したWinMainについて取り上げると、このWinMainのコードをコンパイルするにはリンカオプションで/SUBSYSTEMを WINDOWSに指定しなければなりません。すると、リンカは WinMainという名前の関数を探して、それをプログラムのエントリポイントに設定します。エントリポイントに設定する事で、OSがプログラムを実行するために実行ファイルをメモリに読み込んだ後、どのアドレスからプログラムを実行するか指定する事ができるのです。

指定されたエントリポイントは、リンカーによって実行形式ファイルのヘッダ部分書き込まれます。

よって、例えばmain関数でない別の関数をエントリポイントとしたいのであれば、以下のように指定する事でmain関数のないC言語プログラムを作る事ができます。

#include<stdio.h>
int hoge()
{
    puts("hoge only");
}
gcc -e hoge() a.c

実行結果は以下となります。

hoge only

C++ではなくC言語であるのはちょっとした理由があります。それには 、マングリングというものが起因しています。マングリングについては次項で説明しています。