C言語基礎|返却値を引数に使う

関数を“つなげて”書けると一気に便利になるよ

前の節で、return文が「関数呼出し式の評価結果になる」って話をしました。
ここから一歩進めると、その評価結果(返却値)を、別の関数の引数としてそのまま渡すことができるようになります。

つまりこういう発想です。

  • まず関数Aで計算して値を作る。
  • その値を関数Bに渡して、さらに処理する。
  • 最後に表示する。

この「関数→関数→関数」みたいな つなぎ書き ができるようになると、コードがかなりスッキリします。

まず結論:返却値は“値”なので、そのまま引数にできる

関数呼出し式は評価すると値になります。だから、

  • diff(sqr(x), sqr(y))

みたいに、引数の場所に関数呼出し式が書けるんです。

今回の主役(考え方の整理)

書き方何が起きる?ポイント
f(x)x を f に渡す普通の呼び出し
g(f(x))f(x) の返却値を g に渡す返却値を引数にする
h(f(x), g(y))それぞれ評価してから h に渡す引数は左から順に評価されるとは限らない点に注意(Cでは未規定の場面がある)

最後の注意、ちょい大事です。
「引数の評価順」はC言語だと処理系に任されるケースがあります。今回みたいに 独立した計算(副作用なし)なら問題になりません。安心してOK!

サンプルプログラム

二つの整数を読み込んで、それぞれの絶対値を作り、最後に合計して表示するプログラムを例に解説をします。

  • 関数 abs_int:整数の絶対値を返す
  • 関数 add:二つの整数を足して返す
  • main:add(abs_int(a), abs_int(b)) の形で“返却値を引数に使う”

プログラム例

プロジェクト名:chap6-4-1 ソースファイル名:chap6-4-1.c

Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。

#include <stdio.h>

// n の絶対値を返す
int abs_int(int n)
{
    return n < 0 ? -n : n;
}

// a と b の合計を返す
int add(int a, int b)
{
    return a + b;
}

int main(void)
{
    int a, b;

    puts("2つの整数を入力してください。絶対値の合計を表示します。");
    printf("1つ目:");
    scanf("%d", &a);
    printf("2つ目:");
    scanf("%d", &b);

    printf("絶対値の合計は %d です。\n", add(abs_int(a), abs_int(b)));

    return 0;
}

実行例

2つの整数を入力してください。絶対値の合計を表示します。
1つ目:-7
2つ目:3
絶対値の合計は 10 です。

どんな順番で動くの?

ポイントは 内側の関数呼出し式が先に評価され、その値が外側へ渡ることです。

返却値を引数にする流れ(イメージ)

ステップ起きていること結果の値
1abs_int(a) を評価する例:a=-7 → 7
2abs_int(b) を評価する例:b=3 → 3
3add(7, 3) を呼び出す10
4add の返却値 10 を printf に渡す画面に表示

この「小さい計算を先に作って、次の関数へ渡す」感じが、関数を部品として使うコツです。

登場する命令・書式と役割(ちゃんと整理)

今回出てくる主な命令(関数・文・演算子)

名前書式何をする?
関数呼出し演算子f(実引数)関数 f を呼び出し、返却値があれば値を得る。
return文return 式;関数を終了し、式の値を呼び出し元へ返す。
条件演算子条件 ? 式1 : 式2条件が真なら式1、偽なら式2を選んで値にする。
scanfscanf(書式文字列, アドレス...)キーボード入力を読み込んで変数に格納する。
printfprintf(書式文字列, 値...)値を文字列として整形して表示する。
putsputs(文字列)文字列を表示して改行する。

scanf の超重要ポイント(軽く復習)

scanf は「入力した値を変数へ入れる」ので、変数の置き場所(アドレス)が必要です。
だから &a みたいに & を付けます(配列要素でも &x[i] でしたね)。

なぜこう書くと嬉しいの?(読みやすさの観点)

返却値を引数に使うと、途中の変数を減らしても意味が通ることが多いです。

書き方の比較

書き方特徴
途中変数を使う手順が追いやすい。デバッグしやすい。
返却値をそのまま引数に渡す短く書ける。部品のつながりが見えやすい。

どっちが正しい、ではなくて「場面で使い分け」です。

  • 初学者のうちは、途中変数で段階的に書くのもすごく良い。
  • 慣れてきたら、今みたいに“つなぎ書き”も便利

この記事で使った表・図は何のため?

  • 主役の整理表:返却値を引数にできる理由を最短で理解するため
  • 実行の流れ図:内側→外側へ値が渡る動きを目で追うため
  • 命令一覧表:関数呼出し、return、条件演算子などの役割を見失わないため
  • 書き方比較表:コードの短さと読みやすさのバランス感覚を作るため

演習問題

演習6-3:3乗値を返す関数 cube を作って、返却値を引数に使ってみよう

int型整数の3乗値を返す関数 cube を作成し、
cube の返却値を別の関数の引数として渡して表示するプログラムを作成せよ。

関数プロトタイプ:
int cube(int x);

ここでは「cube の返却値をさらに abs_int に渡して表示」してみます。
マイナスでも安心して確認できるからね。

解答例

プロジェクト名:chap6-4-2 ソースファイル名:chap6-4-2.c

Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。

#include <stdio.h>

int cube(int x)
{
    return x * x * x;
}

int abs_int(int n)
{
    return n < 0 ? -n : n;
}

int main(void)
{
    int x;

    puts("整数を入力してください。3乗の絶対値を表示します。");
    printf("整数:");
    scanf("%d", &x);

    printf("3乗の絶対値は %d です。\n", abs_int(cube(x)));

    return 0;
}

解説

  • cube(x) は関数呼出し式なので、評価すると値になる。
  • その値を abs_int の引数として渡しているのが abs_int(cube(x))
  • 最終的に abs_int の返却値が printf に渡って表示される。

「返却値 → 次の関数の引数」という流れが、ちゃんと体験できる演習です。