C言語のきほん|return文の基本

return文がわかると、関数の結果の渡し方がすっきり見えてくる

C言語で関数を学んでいくと、やがてとても大切になるのが return文 です。
関数は、ただ処理を行うだけでなく、計算した結果や判定した結果を呼び出し元へ返すことができます。そこで使われるのが return文 です。

たとえば、

  • 2つの数の合計を返す
  • 大きいほうの値を返す
  • 条件に応じて結果を返す

といった場面では、return文 が中心になります。

return文 を正しく理解すると、

  • 関数がどのタイミングで終わるのか
  • どんな値を返せるのか
  • return文 をどこに書くと読みやすいのか
  • 1つの値しか直接返せないとはどういう意味か

といった大切な点が見えてきます。

また、C言語では return文 で直接返せる値は基本的に1つだけですが、ポインタを使えば複数の結果を間接的に受け取ることもできます。
この考え方は、これから関数を使いこなしていくうえでとても重要です。

ここでは、まず return文 の基本 にしっかり絞って、値を1つ返す仕組みをやさしく整理していきましょう。

return文とは

return文 は、関数の結果を呼び出し元へ返すための文です。
同時に、return文 が実行された時点で、その関数の処理は終了します。

基本の形は次のようになります。

return 値;

たとえば、整数値を返す関数なら、

return 10;

のように書けます。

また、変数の値を返すこともできます。

return sum;

さらに、計算式をそのまま返すこともできます。

return a + b;

このように、return文 は「値を返す」と「関数を終わらせる」という2つの役割を持っています。

値を1つ返すのが基本

C言語の関数では、return文 で直接返せる値は基本的に1つだけです。

たとえば、2つの整数を受け取って合計を返す関数は、次のように書けます。

int add(int a, int b)
{
    return a + b;
}

この関数は、a と b の和を1つの int 値として返しています。

ここで大事なのは、
「返しているのは1つの結果だけ」
という点です。

もちろん、その1つの値が

  • 計算結果
  • 判定結果
  • 選ばれた値
  • 変換後の値

であることはありますが、return文 1回で直接返せるのは1つです。

サンプルプログラム

ここでは、2つの整数のうち小さいほうを返す関数を作成します。

まずは、結果を変数に入れてから返す形です。

ファイル名:13_14_1.c

// 2つの整数の小さいほうを返すプログラム
#include <stdio.h>

int get_min(int a, int b);

int main(void)
{
    int x = 14;
    int y = 9;

    int result = get_min(x, y);

    printf("%dと%dのうち小さい値は%dです。\n", x, y, result);

    return 0;
}

// 2つの整数の小さいほうを返す関数
int get_min(int a, int b)
{
    int min;

    if (a <= b) {
        min = a;
    }
    else {
        min = b;
    }

    return min;
}

実行結果例

14と9のうち小さい値は9です。

このプログラムでは、get_min 関数が計算結果を result に入れてから、それを return文 で返しています。

変数を返す形

先ほどの get_min 関数では、次のように書いていました。

int min;

if (a <= b) {
    min = a;
}
else {
    min = b;
}

return min;

このように、いったん結果を変数に入れてから return する書き方は、とても基本的で分かりやすいです。

特に学習の初期段階では、

  • どんな値を求めたのか
  • 最後に何を返しているのか

が見やすいのでおすすめです。

計算式や式を直接返す形

一方で、return文 には式を直接書くこともできます。

たとえば、2つの整数の平均 整数の範囲で を返す簡単な関数なら、こう書けます。

int average(int a, int b)
{
    return (a + b) / 2;
}

このように書くと、わざわざ途中結果を格納する変数を用意しなくても済みます。

元の説明でいうと、

int add2(int a, int b)
{
    return a + b;
}

と同じ考え方です。

どちらがよいのか

これは場合によります。

書き方向いている場面
変数に入れてから返す処理が少し長いとき、意味を分かりやすくしたいとき
式を直接返す単純な計算や短い処理のとき

短い式なら直接返しても読みやすいですが、少し複雑になるなら変数に入れてから返すほうが分かりやすいことも多いです。

return文が実行されると関数は終わる

これは return文 でとても大切な性質です。
return文 が実行された時点で、その関数の処理はそこで終了します。

たとえば、次のような関数を見てみます。

int add(int a, int b)
{
    int sum = a + b;
    return sum;
    printf("sum = %d\n", sum);
}

この場合、

printf("sum = %d\n", sum);

は実行されません。

なぜなら、その前の

return sum;

が実行された瞬間に、関数の処理が終わるからです。

つまり、return文 の後ろに書いたコードは、そこに到達できないなら意味がありません。

実行されないコードを別の例で見てみよう

別のシンプルな例に置き換えると、次のようになります。

int square(int n)
{
    int result = n * n;
    return result;
    printf("計算結果は%dです。\n", result);
}

この printf は実行されません。

このようなコードは、読み手を混乱させるので避けたほうがよいです。
return文 のあとに必要な処理があるなら、return より前に書く必要があります。

1つの関数に return文 は複数書ける

C言語では、1つの関数に return文 を複数書くことができます。

たとえば、2つの整数の大きいほうを返す関数は、次のようにも書けます。

int get_max(int a, int b)
{
    if (a >= b) {
        return a;
    }
    else {
        return b;
    }
}

この関数では、

  • 条件が真なら return a;
  • 条件が偽なら return b;

という形で、分岐ごとに return しています。

この書き方は短くて分かりやすい場合も多いです。

複数 return のメリットと注意点

複数の return文 を使うと、条件ごとにその場で結果を返せるので、コードが短くなることがあります。

ただし、関数が長くなって複雑になると、return の場所があちこちに散らばって、流れを追いにくくなることがあります。

書き方特徴
複数 return短く書けることがある
return を1か所にまとめる処理の流れを追いやすい

つまり、簡単な関数なら複数 return でも問題ありませんが、長い関数では注意が必要です。

return を1か所にまとめる書き方

元の説明にもあるように、保守性を考えると return文 を1か所にまとめる書き方が役立つことがあります。

先ほどの get_max を、return を1か所にまとめて書くとこうなります。

int get_max(int a, int b)
{
    int result;

    if (a > b) {
        result = a;
    }
    else {
        result = b;
    }

    return result;
}

この書き方では、どんな場合でも最後に

return result;

で返しています。

この書き方のよさ

  • 最後にどの値を返すかが見やすい
  • 処理の出口が1つなので追いやすい
  • 長い関数で整理しやすい

学習の段階では、こうした書き方に慣れておくと、コードをていねいに整理する練習になります。

return文 の流れを図で見ると分かりやすい

return文 は「関数の中で値を作り、それを呼び出し元へ返す」という流れです。
図で見ると理解しやすくなります。

この図では、関数 get_min の中で求めた値が、return文 によって main 関数へ戻る流れを表しています。
return文 が実行されると、その時点で get_min 関数の処理は終わり、返却値が呼び出し元へ渡されます。

呼び出し側ではどう受け取るのか

return文 で返された値は、関数呼び出しを書いた場所へ戻ってきます。
たとえば、

int result = get_min(x, y);

なら、get_min(x, y) の部分が返却値に置き換わるイメージです。

たとえば返却値が 9 なら、

int result = 9;

のような形になります。

また、返却値は変数に代入するだけでなく、そのまま表示に使うこともできます。

printf("%d\n", get_min(x, y));

あるいは、別の計算にも使えます。

int total = get_min(x, y) + 10;

このように、値を返す関数は式の中で使えるのが大きな特徴です。

return文 で返す値の型に注意する

return文 で返す値は、関数の返却値型と合っていることが大切です。

たとえば、

int get_value(void)

と書いてあるなら、返すのは int 型の値であることが基本です。

return 10;

なら問題ありません。

一方で、返却値型が void の関数では、値を返すことはできません。

void show_message(void)
{
    return 10;
}

これは正しくありません。

void 関数では、必要なら

return;

と書いて途中で関数を終わらせることはできますが、値は返しません。

return文 で直接返せるのは1つだけ

ここまで見てきたように、return文 で直接返せる値は基本的に1つだけです。

たとえば、

  • 合計と平均を両方返したい
  • 横幅と高さを両方返したい
  • 複数の計算結果をまとめて返したい

という場合、return文 だけでは1つしか返せません。

そこでC言語では、変数や配列のアドレスを引数で渡して、その先に結果を書き込むことで、間接的に複数の値を受け取る方法を使います。

これはまさにポインタを使った考え方です。

複数の結果を間接的に受け取る考え方

たとえば、2つの値を関数から受け取りたいなら、次のような考え方ができます。

  • return文 では1つの結果だけ返す
  • それ以外の結果は、引数で渡したポインタ先に書き込む

たとえば、合計と差を両方求めたいときは、こんな形が考えられます。

void calc_values(int a, int b, int *sum, int *diff)
{
    *sum = a + b;
    *diff = a - b;
}

この関数は return文 で直接値を返していませんが、ポインタを通して呼び出し元の変数に結果を書き込めます。

この考え方は、return文 の限界を補う大事な方法です。

サンプルをもう1つ見てみよう

ここでは、return文 を直接使う短い例をもう1つ見ておきます。
内容は、3つの整数の平均を返す関数です。

ファイル名:13_14_2.c

// 3つの整数の平均を返すプログラム
#include <stdio.h>

int average_of_three(int a, int b, int c);

int main(void)
{
    int result = average_of_three(12, 15, 18);

    printf("3つの整数の平均は%dです。\n", result);

    return 0;
}

// 3つの整数の平均を返す関数
int average_of_three(int a, int b, int c)
{
    return (a + b + c) / 3;
}

実行結果例

3つの整数の平均は15です。

この例では、計算式をそのまま return文 に書いています。
短くて意味が分かりやすいので、この形もとても実用的です。

実践問題

次の仕様に従って関数を作成し、main 関数から呼び出して結果を確認してください。

関数宣言

int get_abs_value(int n);

機能
整数 n の絶対値を求める。

返却値
求めた絶対値

実行結果例

-12 の絶対値は 12 です。

main 関数で表示

解答例

ファイル名:13_14_3.c

// 整数の絶対値を返すプログラム
#include <stdio.h>

int get_abs_value(int n);

int main(void)
{
    int number = -12;
    int result = get_abs_value(number);

    printf("%d の絶対値は %d です。\n", number, result);

    return 0;
}

// 整数の絶対値を返す関数
int get_abs_value(int n)
{
    int result;

    if (n < 0) {
        result = -n;
    }
    else {
        result = n;
    }

    return result;
}

解答例の解説

この問題では、return文 の基本がしっかり入っています。

まず、関数宣言

int get_abs_value(int n);

から、この関数は

  • int 型の引数を1つ受け取る
  • int 型の値を1つ返す

ことが分かります。

関数の中では、if 文で条件分岐を行い、結果を result に入れています。
そして最後に

return result;

で呼び出し元へ返しています。

このように、

  1. 結果を求める
  2. 変数に入れる
  3. return で返す

という流れは、とても基本的で分かりやすい形です。

複数 return にした場合の書き方

同じ関数は、複数 return を使って次のようにも書けます。

int get_abs_value(int n)
{
    if (n < 0) {
        return -n;
    }
    else {
        return n;
    }
}

これでも正しく動きます。
短い関数では、このように書くほうが簡潔で読みやすいこともあります。

ただし、関数が長くなってきたときには、return の位置が多すぎないかを意識することが大切です。

学習のコツ

return文 を理解するときは、次の3つを意識すると整理しやすいです。

ポイント意識したいこと
return文 の役割値を返して関数を終了する
返せる値の数直接返せるのは基本的に1つ
書き方短い関数では直接返す、長い関数では整理して返す

特に、
return文 が実行されたら、その先の処理は行われない
という点はとても重要です。

また、コードを書くときは「この関数は何を返したいのか」を先に意識すると、return文 の位置や書き方が決めやすくなります。