Tips & Information 今回のお題:
『main 関数の返値』


●動機

星屑さん>あとWinMainの戻り値って意味があるんですか?
たかぼー>これは知らないです(ぉ
たかぼー>きっと他の人が答えてくれますよ(笑<NUTS氏とか

という会話が、たかぼーのページの掲示板でされてたとかされてなかったとか。

この書き込みを読んでたのか読んでなかったのか、

hiro「main の返値って意味無いじゃん、どこに返るよ?」

とかいうことを授業中に訊かれてみたり。

main の返値が int だって事を知らん奴も居てみたり、stdlib.h に 「#define EXIT_SUCCESS 0」「#define EXIT_FAILURE 1」 とか書かれているのを知らん奴も居てみたり、なんなんでしょう、この状況は。

仕方ないから、この状況を少しでも改善しようと思って、こんなものを書くわけです。

●内容

まず、結論から言うと、main() の返値や、exit() の引数は「そのプログラムの呼び出し元」に返されます。
で、その「呼び出し元」は大きく 2 つに分けられます。

まず 1 つ目は shell です。(MS-DOS だったら command.com ですね) プログラムの返値は、コマンドインタプリタである command.com に返されて、 バッチファイルでの分岐処理に使われたりします。

例えば、「マシンに故障があったら 1 を、無ければ 0 を返すプログラム check.exe」 というプログラムがあったとしたら、

check.exe
if errorlevel 1 goto NG
if errorlevel 0 goto OK
:NG
echo マシンに異常があります. 点検して下さい.
goto end
:OK
echo マシンに異常は見つかりませんでした.
goto end
:end

というバッチファイルを組むことによって、解りやすく利用することが出来ます。

2 つ目は、他のプログラムが呼び出し元になる場合です。
実際には、C 言語なら spawn() 系の関数で呼ばれる場合ですが、 こうして呼び出されたプログラムの返値は、呼び出した関数の返値になります。

例えば、さっきの check.exe を子プロセスとして呼ぶ場合には、

int rslt;
rslt = spawnl( P_WAIT, "check.exe", "check.exe", NULL );
switch( rslt )
{
    case 0:
        printf( "マシンに異常は見つかりませんでした." );
        break;
    case 1:
        printf( "マシンに異常があります. 点検して下さい." );
        break;
}

といった感じになります。
こうして、他のプログラムとかコマンドを、ちょっとした関数の代わりにして使ったりできるわけですね。

# 実際にコンパイルして走らせてはいないので一寸怪しいのですが……。
# なお、spawn() 系の関数は ANSI 標準の関数セットには含まれていません。

他にも、OS のカーネルから呼ばれる、shell 等のプログラムの返値がカーネルに返る場合が考えられますが、 その辺はよく解らないので省略します。(エー

どの場合でも、main() の返値や exit() の引数は、「そのプログラム自体の返値」になって、 他のプログラムとの連携に役立っているというわけですね。

なお、「プログラムが値を返す」というのは、「main 関数が値を返す」ということと同じですから、 正しい main 関数のプロトタイプは、 int main( int argc, char **argv ); となります。

●ちなみに

行儀の良いプログラムは、正常終了時には零を、異常終了時には非零を返します。

#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1

みたいなマクロが stdlib.h あたりにあるとおもいますが、これがそれです。

FILE *fp;
fp = fopen( "test.txt", "r" );
if( fp == NULL )
    exit( EXIT_FAILURE );

みたいな使い方をされることが多いですね。

当然、main関数の末尾は、

return EXIT_SUCCESS;

となるわけです。

2002/02/10 追記: p2 さんのページに載ってたのを転写。
% echo $status  # csh 系の場合
% echo $?       # sh 系の場合

で、直前に実行されたプログラムの返値が表示される。


戻る