C言語基礎|関数の基本

人まかせ卒業!自分の“便利部品”を作ろう

これまでのプログラムは、表示は printf、入力は scanf…という感じで、既に用意された関数に「お願い!」して動かしてきましたよね。
でも、実務でも学習でも、ずっとそれだけだとすぐ限界が来ます。

そこで登場するのが 自分で作る関数
関数を作れるようになると、プログラムは「長い1本の文章」から「読みやすい部品の組み立て」に変わります。結果として、

  • 同じ処理を何度も書かずに済む
  • ミスが減る(修正も1か所でOK)
  • 処理の意味がコードから伝わりやすい

…という、うれしいことがまとめて起こります。

関数ってなに?(ざっくりイメージ)

関数は、入力(引数)を受け取り、処理して、必要なら結果(戻り値)を返す部品です。
ゲーム機のカセットや家電のボタンみたいに、「押すと一定の仕事をしてくれる仕組み」と思ってOKです。

関数のイメージ(入力→処理→出力)

入力(引数)関数(処理)出力(戻り値)
2つの整数大きい方を選ぶ大きい方の整数

この図は「関数が何を受け取り、何を返すか」を整理するのに便利です。
関数を作る前に、まずこの“流れ”を言葉にできるようになるのが第一歩です。

main 関数とライブラリ関数(主役と道具箱)

Cのプログラムには基本的に main 関数が1つ必要です。
プログラムが起動すると、まずここから実行されます。

main 関数の最小形

#include <stdio.h>

int main(void)
{
    return 0;
}

それぞれの役割(表でスッキリ)

種類役割
main 関数mainプログラムの開始地点。ここから動く
ライブラリ関数printf, scanf, puts便利な道具(標準で用意されている)
自作関数自分で定義する関数自分のプログラム専用の便利部品

今までは主に「ライブラリ関数を使う側」でした。
ここからは 作る側(関数定義) に進みます。

関数定義と関数呼出し(作る・使う)

関数を使いこなすには、次の2つをセットで覚えるのがコツです。

やること呼び名何をする?
関数を作る関数定義処理の中身を用意する。
関数を使う関数呼出し必要なときに関数を実行する。

関数は「作って終わり」でも「呼ぶだけ」でも片手落ち。
両方セットで理解すると、一気にラクになります。

関数定義の形(max2 を例に分解)

質問文にある「2つの整数を受け取って大きいほうを返す関数」は、たとえばこう書けます。

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

関数定義の構造

部品意味
返却値型int戻り値の型(返す値の型)
関数名max2呼び出すための名前
仮引数int a, int b関数が受け取る入力
関数本体{ ... }実際の処理
return 文return a;呼び出し元へ値を返す

この表は「関数って何でできてるの?」を視覚的に整理するためのものです。
特に初心者が混乱しやすいのが 返却値型仮引数 の違いなので、ここを意識すると理解が安定します。

return は何をする命令?(書式と働き)

return は「関数の仕事を終えて、呼び出し元へ戻る」ための命令です。
値を返す場合と、返さない場合で形が変わります。

return の書式

書式使いどころ
return 式;値を返す(例:int を返す関数)
return;値を返さない(返却値型が void の関数)

例:値を返す関数

return a;
  • この時点で関数は終了
  • 呼び出し元へ a の値が渡る

仮引数と実引数(名前が似てて混乱しがち)

  • 仮引数:関数側で受け取る変数(max2 の a, b)
  • 実引数:呼び出す側で渡す値や変数

表:仮引数と実引数

呼び出す側関数側
max2(x, y) の x, yint a, int b の a, b

「呼び出す側の値が、関数側の仮引数に入ってから処理が走る」
この順番を意識すると、スッと理解できます。

サンプルプログラム

3つの整数の中央値(真ん中の値)を返す関数を例に解説をします。

プログラム例:median3(3つの値の真ん中を返す)

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

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

#include <stdio.h>

// 3つの整数の中央値(真ん中の値)を返す関数
int median3(int a, int b, int c)
{
    if ((a >= b && a <= c) || (a >= c && a <= b))
        return a;
    else if ((b >= a && b <= c) || (b >= c && b <= a))
        return b;
    else
        return c;
}

int main(void)
{
    int x, y, z;

    puts("3つの整数を入力してください。真ん中の値を表示します。");
    printf("1つ目:");
    scanf("%d", &x);
    printf("2つ目:");
    scanf("%d", &y);
    printf("3つ目:");
    scanf("%d", &z);

    printf("真ん中の値は %d です。\n", median3(x, y, z));

    return 0;
}

このプログラムで確認できるポイント

学ぶ点どこを見る?何が分かる?
関数定義int median3(int a, int b, int c)返却値型・関数名・仮引数
関数本体if ... return ...条件で分岐して return
関数呼出しmedian3(x, y, z)実引数が仮引数へ渡る
ライブラリ関数利用puts, printf, scanf既存関数を組み合わせる

この表は「関数の基本要素を、実コードのどこで見ればいいか」を対応づけるためのものです。
読むときに迷子になりにくくなります。

ちょい注意:関数の中で使う変数の場所

関数の中だけで使う変数は、基本的にその関数の { } の中で宣言します。
そして、仮引数と同じ名前の変数は宣言できません(名前がぶつかるからです)。