C言語の関数で戻り値を返す方法【return文】

385, 2022-01-07

目次

C言語の関数で戻り値を返す方法

function

C言語では関数を使うことができます。
関数内の処理が終わって、関数から結果を得たい場合があります。
そういう時は関数の戻り値を使います

関数の戻り値はreturn文で返すことができます。
この記事ではC言語の関数で戻り値を返す方法について具体的に解説します。

  • 戻り値とは

  • return文とは

  • 関数から戻り値を返す

  • 足し算の結果を戻り値で返す

  • 戻り値と構造体

  • ローカル変数のポインタは戻り値で返さない

  • 複数のreturn文

関連記事
C言語の関数で戻り値にポインタを使う
C言語の関数で戻り値を返す方法【return文】
C言語の関数ポインタを引数に渡す方法
C言語の構造体を関数で扱う
C言語の関数の引数が多くなった時の対処方法【引数爆発】

戻り値とは

laptop

「戻り値(もどりち)」とは「関数から戻ってくる値」あるいは「関数から戻す値」のことを言います。
C言語の関数はたとえば↓のように呼び出します。

func();

func()を呼び出すと、func()はその関数の中で色々な仕事をします。
そしてその仕事の結果を関数の呼び出し側で受け取りたい場合があります。
たとえばfunc()1100までの合計を返す関数だったら、

int sum = func();

と言う風に書いて、func()の計算結果をsumという変数で受け取ります。
このとき、このint型の変数sumのことを「func()関数の戻り値」と言います。

関数の戻り値はint型だけでなく、あらゆる型を使えます。
たとえば文字列定数を返す関数だったら、戻り値の受け取り方は↓のようになります。

const char *result = func();

ちなみにresult(リザルト)という変数名は「結果」という意味を持つ英単語です。
func()の「計算結果」を受け取るから戻り値の変数名がresultになるというわけです。

「戻り値」は「返り値」とも言い換えることができます。
関数から戻る値、あるいは関数から返る値、ということですね。
どちらも同じ意味ですがどちらを使うかは完全に趣味の話になります。
使いやすいほうか、特にこだわりがなければ「戻り値」を使えばいいでしょう。

return文とは

return

関数の中から戻り値を返すわけですが、その時に使われる文がreturn文です。
returnは「返す」とか「返却する」という意味を持つ英単語です。
return文は↓のように使います。

return;

あるいは

return 戻り値;

returnと書いてその次にセミコロンを書くと、これは戻り値を返さないreturn文になります。
関数の戻り値の型がvoid型である場合にこのreturn文は使われます。

関数の戻り値の型とは、関数名の前に書いてある型のことをいいます。
たとえば↓のような関数では

void func1() { ... }
int func2() { ... }

func1()の戻り値の型はvoid(何もない)型、func2()の戻り値の型はint型になります。

関数の戻り値の型がint型などの場合は、returnと書いてその次に戻り値を書きます。
そして戻り値の次にセミコロンを書きます。

return 戻り値;

これは例えばint型の戻り値であれば↓のように書きます。

return 1;

↑のコードは整数の1を戻り値として返すreturn文です。
あるいは変数を戻り値として返すこともあります。

int a = 1;
return a;

あるいは戻り値の部分に式を書くこともできます。

return 1 + 2;

この場合は1 + 2の結果が戻り値となります。

関数のreturn文の書き方は関数の戻り値の型に依存します
void型であれば戻り値は必要ありませんし、int型であれば戻り値はint型にしないといけません。
あるいはポインタ型だったら戻り値はポインタにする必要があります。

それから関数のreturn文は戻り値をコピーで返します。
つまりreturn文に書いた戻り値は、コピーされて関数の呼び出し側に返されます。
メンバが多い構造体などを返す場合は、コピーのコストがかかることがあります。
この辺は心にとどめておいた方が良いでしょう。

関数から戻り値を返す

number

それでは実際に関数から戻り値を返してみたいと思います
↓のような関数を定義します。

// 整数1を返す関数
int get_one(void) {
    return 1;
}

↑の関数get_one()の戻り値の型はintです。
つまりこの関数はint型の返り値を返します。
get_one()内ではreturn 1;とやって整数1returnしています。
この関数を使ってコードを書くと↓のようになります。

#include <stdio.h>

// 整数1を返す関数
int get_one(void) {
    return 1;
}

int main(void) {
    // get_one()を呼び出して戻り値resultを受け取る
    int result = get_one();

    // resultを出力する
    printf("result = %d\n", result);

    return 0;
}

↑のコードをコンパイルして実行すると結果は↓になります。

result = 1

足し算の結果を戻り値で返す

関数に足し算をさせて、その足し算の結果をreturn文で返すという関数を書きます。

// aとbを足し算してその結果を返す
int add(int a, int b) {
    return a + b;
}

↑のようにreturn a + b;と書くと、戻り値はa + bの結果になります。
引数a1で、引数b2だった場合はa + b1 + 2になります。
そのためその時の戻り値は3になります。

この関数を使ってコードを書くと↓のようになります。

#include <stdio.h>

// aとbを足し算してその結果を返す
int add(int a, int b) {
    return a + b;
}

int main(void) {
    // add()の計算結果をresultで受け取る
    int result = add(1, 2);

    // resultを出力する
    printf("result = %d\n", result);

    return 0;
}

↑のコードをコンパイルして実行すると↓の結果になります。

result = 3

戻り値と構造体

structure

関数の戻り値では構造体を返すことができます。

#include <stdio.h>

// 動物を表す構造体
struct Animal {
    int age;  // 年齢
    char name[40];  // 名前
};

// 構造体を定義して戻り値として返す関数
struct Animal create_animal(void) {
    struct Animal animal = { 20, "Tama" };
    return animal;
}

int main(void) {
    // create_animal()の戻り値をanimalで受け取る
    struct Animal animal = create_animal();

    // animalのメンバを出力
    printf("age[%d] name[%s]\n", animal.age, animal.name);
    return 0;
}

↑のコードを実行すると↓のような結果になります。

age[20] name[Tama]

↑の関数create_animal()は構造体struct Animalの変数を返す関数です。
この関数の戻り値の型はstruct Animalになっています。

create_animal()内で作成したanimal変数はreturn文でコピーされて返されます。
main()関数側でcreate_animal()の結果を受け取ると、この結果はそのコピーされたデータになります。
つまりageの値20nameの値Tamaがコピーされているということになります。

このように構造体をreturn文で返すと、そのメンバがすべてコピーされます。
メンバが多すぎる構造体を返す関数が頻繁に呼び出される場合は、プログラムの速度に影響が出る場合もありますので注意が必要です。

まあ大抵はそこまで神経質になる必要もないやね

そうだね

ローカル変数のポインタは戻り値で返さない

arrow

関数の戻り値ではポインタを返すこともできます。
たとえば↓はint型のポインタを返す関数です。

int *get_ptr(void) {
    int a = 1;
    return &a;
}

ちなみにこのような関数は作ってはいけません
なぜかというと、↑の関数get_ptr()はローカル変数のポインタを返しているからです。

関数内のローカル変数は関数が終了すると破棄されます。
そのためget_ptr()が返すポインタは不正なものになります。
関数の呼び出し側でそのポインタにアクセスすると、プログラムがクラッシュする場合もあります。

複数のreturn文

multi

return文は関数内で複数書くことができます。

int func(void) {
    return 1;
    return 2;
    return 3;
}

↑のような関数にした場合、最初にreturn 1;が実行されます。
return文は実行されるとその時点で関数が終了します。
そのためreturn 2;return 3;は実行されません。

たとえばif文の分岐でreturn文を複数書く場合もあります。

int func(void) {
    int a = 1;

    if (a == 0) {
        return 0;
    } else {
        return 1;
    }
}

↑のような関数では実行されるif文の中のreturn文が実行されます。
変数a1ですが、if (a == 0)という条件は真にならないのでreturn 0;は実行されません。
代わりにelseの中のreturn 1;が実行されます。
return 1;が実行されるとその時点で関数func()は終了します。
そのためそれ以降の処理は実行されません。

おわりに

今回はC言語の関数の戻り値について具体的に見てきました。
関数は戻り値を返すことでその計算結果を外に出すことができます。

関数の戻り値を受け取ろう