【C言語】main関数のreturnの役割

C言語におけるmain関数のreturnの解説ページアイキャッチ

このページでは、C言語における main 関数 の return の役割について解説していきたいと思います。

意味も分からず、おまじないのように、とにかく main 関数に return 0; を記述している方もおられるかもしれませんが、main 関数の return での値の返却には重要な役割があります。C言語の学習中・プログラミングの練習中である方であれば、何も考えずに return 0; を実行する or return しないのでも良いのですが、実用性を考えると適切な値を return で返却する方が本当は良いです。

この辺りの理由も含め、main 関数の return の役割について説明していきたいと思います。

main 関数の return の役割

基本的に、main 関数の return の役割は他の関数における return と同じで、関数を実行した相手に結果を伝えることが役割になります。

return の役割

main 以外の関数の場合は、他の関数から呼び出しされることになるため、その呼び出し元の関数に対して関数の結果を伝えることになります。

main関数以外の関数のreturnの説明図

それに対し、main 関数の場合はプログラム実行時に最初に呼び出しされる関数であるため、他の関数ではなくプログラム実行者に対してプログラムの結果を伝えることになります。言い方を変えれば、main 関数で return した値がプログラムの結果として扱われます。

main関数のreturnの説明図

スポンサーリンク

「結果を伝える」ことの意味

では関数が「結果を伝える」こと自体の意味とは何になるでしょうか?

main 以外の関数の場合

これも main 以外の関数の場合と対比して考えると分かりやすいと思います。

main 以外の関数の場合は、呼び出し側の関数が関数の結果を利用できるようにするために関数が結果を伝えることになります。

例えば、ある関数が true or false を返却する場合、その関数の呼び出し側は返却値が true の場合と false の場合とで分岐を行い、それぞれに対して異なる処理を行うようなことが可能になります。

関数の結果の利用例1
/* xが偶数であるかどうかを判断する */
bool is_even(int x) {
    if (x % 2 == 0) {
        return true;
    } else {
        return false;
    }
}

void caller(int x) {
    bool  ret = is_even(x);
    if (ret) {
        printf("%dは偶数です\n", x);
    } else {
        printf("%dは奇数です\n", x);
    }
}

また、ある関数が整数を返却する場合、その関数の呼び出し側で返却値を利用して単に表示を行うようなこともできますし、その返却値を利用した演算を行うようなことも可能になります。

関数の結果の利用例2
/* 価格valueの半額を求める*/
int calcHalf(int value) {
    return value / 2;
}

int caller(int value) {
    return calcHalf(value) * 1.1;
}

main 関数の場合

では main 関数の場合はどうでしょう?

結局これも main 以外の関数の場合と同様です。ただし、呼び出し側の関数ではなく、プログラム実行者がプログラムの結果を利用できるようにするためmain 関数が結果を伝えることになります。

では、このプログラム実行者とは誰になるのかというと、直接的には OS (Operating System) となるようです。つまり、プログラムの結果、すなわち main 関数から return された値は OS が受け取ります。

そう聞くと一般ユーザーである我々からすると main 関数から return される値は無関係のようにも思えますが、例えばシェルスクリプトやバッチファイル、さらには Python スクリプトや他のC言語プログラムからも、この main 関数から return された値を受け取ることが可能です。そして、これらが main 関数から return された値を受け取り、その値を利用することができます。

例えば、シェルスクリプトからプログラムを実行し、その後の処理にプログラムの結果を利用するようなこともできます。

プログラムの結果を利用する例

ちょっと抽象的な説明になっていますので、ここで具体例としてシェルスクリプトを用いた「プログラムの結果を利用する例」を紹介しておきたいと思います。

下記は、シェルスクリプトから sample.exe というプログラムを実行し、プログラムが正常終了した場合のみ後続の処理を継続するような例となります。

プログラムの結果の利用例
#!/bin/sh

# sample.exeを実行
./sample.exe

# sample.exeの結果が0以外の場合はスクリプト終了
if [ "$?" -ne "0" ]; then
    echo "sample error"
    exit 1
fi

echo "next step..."

# 後続の処理(略)

いきなりシェルスクリプトを示されても意味不明と感じる方も多いと思いますので、ポイントのみ補足で説明しておきます。

まず、下記の行が sample.exe の実行を行なっている部分になります(シェルスクリプトを実行しているフォルダ内に存在する sample.exe を実行している)。

プログラムの結果の利用
./sample.exe

sample.exe はC言語のソースコードからコンパイルして生成されたプログラムであることを想定していますが、別に他の言語で記述されたプログラムでも良いですし、サイトからダウンロードしてきたようなプログラムでも良いです。要は、C言語のソースコードからコンパイルして生成されたプログラムも含め、プログラムは他のプログラムやスクリプト等から実行可能というところがポイントになります。

そして、sample.exe の実行が終了すると、下記の処理が行われることになります。

プログラムの結果の利用
# sample.exeの結果が0以外の場合はスクリプト終了
if [ "$?" -ne "0" ]; then
    echo "sample error"
    exit 1
fi

ここでポイントになるのが $? です。この $? は、直前に実行したプログラム(コマンド)の結果が格納されている変数になります。プログラムやコマンドが実行されるたびに自動的に $? に結果が格納されます。上記においては、$? に格納されている値が 0 でない場合はエラーであることを echo で出力し、exit でスクリプトを終了するようにしています。

そして、直前に実行されたプログラムのソースコードがC言語で記述されている場合、$? には main 関数から return された値が格納されることになります。

例えば、下記のようなソースコードからコンパイルを行なって sample.exe を生成した場合、text.txt が存在して開ける場合は main 関数が 0return しますが、text.txt が存在しない場合は 1return することになります。

プログラムの結果の返却例
#include <stdio.h>

int main(void) {
    FILE *fp;
    fp = fopen("text.txt", "r");
    if (fp == NULL) {
        printf("%sが開けません\n", "text.txt");
        return 1;
    }

    fclose(fp);

    return 0;
}

したがって、上記のシェルスクリプトにおいては text.txt が存在して開ける場合のみ $?0 が格納され、後続の処理が継続して行われることになります(後続の処理の記述は省略していますが…)。

ですので、例えば後続の処理が text.txt が存在しないと実行しても意味のないものであれば(例えば後続の処理が “text.txt の文字数をカウントする” である場合など)、上記の if 文の中の exit により直ちにスクリプトを終了することができて無駄な処理の実行を防ぐことができるようになります。

簡単な例ですが、シェルスクリプトからプログラムの実行結果を利用することでメリットがあることは伝わったのではないかと思います。

ここで、もう1つポイントを挙げておくと、それは上記のシェルスクリプトにおける exit 1 の部分になります。exit はシェルスクリプトの処理を終了するコマンドなのですが、引数を指定することで特定の値を返却することができるようになっています。つまり、exit 1 により 1 が返却されることになります。そして、この返却値は上記のスクリプトの実行者が受け取ることができ、受け取った側でこの返却値を利用することが可能です。

このように、C言語に限らず、基本的にプログラムやスクリプトは実行者側に値を返却することができるようになっています。そして、その値を実行者側で利用してもらうことが可能となっています。

様々な種類のプログラムやスクリプトが返却値を返却する様子

値の返却の仕方は言語等によって異なるので注意してください。例えば Python スクリプトでは return ではなく sys.exit(返却値) のように exit 関数を利用して値を返却するようになっています(返却しない場合は 0 が自動的に返却される)。

また、あなたがプログラムを実行したり、プログラムを実行するシェルスクリプトやバッチファイルを作成する場合は、プログラムの実行結果を受け取ることができるということも覚えておくと良いと思います。これにより、プログラムの結果に応じた処理の分岐などを実現するようなことも可能になります。

return する値の重要性

ただし、上記の例のようにプログラムの結果を上手く利用することが可能なのは、プログラムの結果が適切に返却されるようになっている場合のみとなります。例えばエラーの有無などに関わらず、どんな場合でもプログラムの結果が 0 であるのであれば、プログラムの結果を利用する意味がありません。

つまり、プログラム実行者がプログラムの結果を上手く利用できるようにするためには、main 関数から return する値を適切に設定するようにする必要があります。特にプログラムの結果は 0 の場合に「正常終了した」と考えるのが通例(特に Unix 系の OS では)なので、プログラムが正常に終了した場合は 0 を、プログラムがエラー終了した場合などは 0 以外を return するようにしておいた方が良いです。

特に覚えておいていただきたいのは、プログラムは単体で動作するものだけでなく、他のプログラムと連携して動作するものも多いという点になります。例えば、あるプログラムを実行し、その実行結果がエラーの場合には後続の処理の実行を中止するようなことも多いです。

プログラムの結果に応じて処理を切り替える様子

特にシェルスクリプトやバッチファイルで何かしらの手順を自動化する際は、このように複数のプログラムを連携して動作させるようなことが多いと思います。

このような、自身が開発したプログラムを利用して連携動作させるような場合は main 関数が return する値が重要となりますので、main 関数から return する値は適切に設定しておく方が良いです。

もちろん、勉強用に作成しているプログラムであったり、単体で動作することを前提としているプログラムのような場合は main 関数から return する値はてきとうでも良いのですが、それでも main 関数の return 値は意味がないものではなく、この値を受け取る相手が存在することは覚えておくと良いと思います。

ちなみに、C言語の main 関数では return の記述を省略することもできますが、この場合でも結局 main 関数の最後で return 0 が実行されるようになっています(C99以降)。

スポンサーリンク

まとめ

このページではC言語における main 関数の return の役割について解説しました!

main 関数の return の役割は「プログラム実行者にプログラムの結果を伝えること」になります。このプログラムの結果はシェルスクリプトやバッチファイル等で受け取ることができ、これらからプログラムの結果を利用することが可能になります。

単体で動作することを想定しているプログラムであれば main 関数の return 値はてきとうに 0 にしておいても良いですが、自身が開発したプログラムの結果を受け取る相手がいることは覚えておいた方が良いと思います。また、シェルスクリプトやバッチファイルを作成するような場合は、実行するプログラムの結果を取得可能であることも是非覚えておきましょう!

この結果を利用することで、シェルスクリプトやバッチファイル等で実現可能な処理の幅も広がると思います!

オススメの参考書

C言語学習中だけど分からないことが多くて挫折しそう...という方には、下記の「スッキリわかるC言語入門」がオススメです!

まず学習を進める上で、参考書は2冊持っておくことをオススメします。この理由は下記の2つです。

  • 参考書によって、解説の仕方は異なる
  • 読み手によって、理解しやすい解説の仕方は異なる

ある人の説明聞いても理解できなかったけど、他の人からちょっと違った観点での説明を聞いて「あー、そういうことね!」って簡単に理解できた経験をお持ちの方も多いのではないでしょうか?

それと同じで、1冊の参考書を読んで理解できない事も、他の参考書とは異なる内容の解説を読むことで理解できる可能性があります。

なので、参考書は2冊持っておいた方が学習時に挫折しにくいというのが私の考えです。

特に上記の「スッキリわかるC言語入門」は、他の参考書とは違った切り口での解説が豊富で、他の参考書で理解できなかった内容に対して違った観点での解説を読むことができ、オススメです。題名の通り「なぜそうなるのか?」がスッキリ理解できるような解説内容にもなっており、C言語入門書としてもかなり分かりやすい参考書だと思います。

もちろんネット等でも色んな観点からの解説を読むことが出来ますので、分からない点は別の人・別の参考書の解説を読んで解決していきましょう!もちろん私のサイトも参考にしていただけると嬉しいです!

入門用のオススメ参考書は下記ページでも紹介していますので、こちらも是非参考にしていただければと思います。

https://daeudaeu.com/c_reference_book/

同じカテゴリのページ一覧を表示

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です