C言語のきほん|関数の4つのパターン

引数と返却値の違いがわかると、関数の使い分けがぐっと見えてくる

C言語の関数を学び始めると、まずは「関数を作る」「関数を呼び出す」という流れに慣れていきます。
ただ、関数はどれも同じ形をしているわけではありません。関数によっては値を受け取るものもあれば、結果を返すものもありますし、何も受け取らず何も返さないものもあります。

この違いをしっかり理解すると、
「この処理はどんな関数にすればよいのか」
「この場面では引数が必要なのか」
「結果を返したほうがよいのか」
といった判断がしやすくなります。

関数は、単に文法として覚えるだけではなく、役割に合わせて形を選ぶことがとても大切です。
そのために押さえておきたいのが、関数の4つのパターンです。

  • 引数も返却値も持たない関数
  • 引数だけ持つ関数
  • 返却値だけ持つ関数
  • 引数と返却値の両方を持つ関数

この4つを整理して理解しておくと、関数の使い方が一気に分かりやすくなります。
ここでは、それぞれの違いをやさしく確認しながら、どんな場面で使われるのかを具体例と一緒に見ていきましょう。

関数の4つのパターンとは

関数は、引数を受け取るかどうか返却値を返すかどうかで、4つの基本パターンに分けられます。

まずは全体を表で整理してみましょう。

パターン宣言例特徴
引数なし・返却値なしvoid func(void);受け取らず、返さない
引数あり・返却値なしvoid func(int n);値を受け取るが、結果は返さない
引数なし・返却値ありint func(void);値は受け取らないが、結果を返す
引数あり・返却値ありint func(int n);値を受け取り、結果も返す

ここで大切なのが void の意味です。
void は「何もない」という意味を表します。

たとえば、

void func(void);

なら、

  • 返却値の型が void → 何も返さない
  • 引数の型が void → 何も受け取らない

という意味になります。

つまり、void は「ここには値がありません」と明示するための書き方です。

4つのパターンを先にざっくりイメージしよう

4つのパターンは、次のように考えるとイメージしやすいです。

パターンたとえ
引数なし・返却値なし呼ばれたら決まった動きをするだけ
引数あり・返却値なし渡された内容に応じて動くが、結果は返さない
引数なし・返却値あり自分で何かを用意して返す
引数あり・返却値あり受け取った値をもとに計算して返す

この見方をしておくと、関数を作るときに
「この関数は何を受け取る必要があるかな」
「呼び出し元へ結果を返したほうがいいかな」
と考えやすくなります。

引数も返却値も持たない関数

引数も返却値も持たない関数は、決まった処理を行うだけの関数です。
呼び出し側から何かを渡す必要もなく、処理結果を受け取る必要もありません。

宣言は次の形です。

void func(void);

シンプルな例

元の greet 関数の例を別の内容に置き換えて、ここでは「開始メッセージを表示する関数」にしてみます。

ファイル名:13_6_1.c

// 引数も返却値も持たない関数の例
#include <stdio.h>

void show_start_message(void);

int main(void)
{
    show_start_message();
    return 0;
}

// 開始メッセージを表示する関数
void show_start_message(void)
{
    printf("プログラムを開始します。\n");
}

実行結果例

プログラムを開始します。

この関数の特徴

この関数では、呼び出し側は

show_start_message();

と書くだけです。
実引数がないので、丸かっこの中には何も書きません。

また、返却値もないため、

int x = show_start_message();

のように受け取ることもありません。

どんなときに使うのか

このタイプは、たとえば次のような場面で使いやすいです。

  • 決まったメッセージを表示する
  • 画面の見出しを表示する
  • 初期案内を出す
  • 特定の定型処理を実行する

つまり、毎回同じ動作をする部品として使いやすい関数です。

return は必要か

返却値がない関数では、最後に return を書かなくても問題ありません。
関数の終わりの } まで到達すれば、その時点で呼び出し元に戻ります。

ただし、途中で処理を終わらせたい場合は、

return;

と書くことがあります。

たとえば次のような形です。

void show_message(int flag)
{
    if (flag == 0) {
        return;
    }

    printf("メッセージを表示します。\n");
}

この return は「値を返す」のではなく、ここで関数を終わらせるために使っています。

引数だけ持つ関数

次は、引数は受け取るけれど返却値は返さない関数です。

宣言は次の形になります。

void func(int n);

このタイプは、呼び出し元から値を受け取って、それに応じた処理を行います。
ただし、結果を呼び出し元へ返すことはありません。

シンプルな例

たとえば、受け取った回数だけメッセージを表示する関数を考えてみます。

ファイル名:13_6_2.c

// 引数だけ持つ関数の例
#include <stdio.h>

void print_hello_times(int count);

int main(void)
{
    print_hello_times(3);
    return 0;
}

// 指定された回数だけメッセージを表示する関数
void print_hello_times(int count)
{
    int i;

    for (i = 0; i < count; i++) {
        printf("おはようございます。\n");
    }
}

実行結果例

おはようございます。
おはようございます。
おはようございます。

この関数の特徴

この関数は、count という引数を受け取っています。
つまり、呼び出し側が値を渡すことで、関数の動きを変えられます。

print_hello_times(3);

なら3回表示し、

print_hello_times(5);

なら5回表示します。

ただし、この関数は返却値がないので、結果を変数に代入することはしません。

どんなときに使うのか

このタイプは、たとえば次のような場面に向いています。

  • 回数を受け取って表示する
  • 名前や点数を受け取って表示する
  • 渡された値を使って画面に出力する
  • ある値をもとに処理だけ行う

つまり、入力は必要だけれど、結果は返さなくてよい処理に向いています。

返却値だけ持つ関数

次は、引数は受け取らないが返却値は返す関数です。

宣言は次のようになります。

int func(void);

このタイプは、関数の中で何かの値を作り、それを呼び出し元へ返します。
外から値をもらわなくても動作できるのが特徴です。

シンプルな例

たとえば、固定のラッキーナンバーを返す関数を考えてみます。

ファイル名:13_6_3.c

// 返却値だけ持つ関数の例
#include <stdio.h>

int get_lucky_number(void);

int main(void)
{
    int number = get_lucky_number();

    printf("今日のラッキーナンバーは%dです。\n", number);

    return 0;
}

// ラッキーナンバーを返す関数
int get_lucky_number(void)
{
    return 7;
}

実行結果例

今日のラッキーナンバーは7です。

この関数の特徴

この関数は引数を受け取らないので、

get_lucky_number();

のように呼び出します。

ただし、返却値があるので、そのまま使ったり変数に代入したりできます。

int number = get_lucky_number();

ここでは、関数が返した 7 が number に入ります。

どんなときに使うのか

このタイプは、たとえば次のような場面で使えます。

  • 初期値を返す
  • 現在の設定値を返す
  • 固定の情報を返す
  • 入力を受けずに内部で決まる値を返す

つまり、外から材料をもらわなくても結果を返せる関数です。

引数と返却値の両方を持つ関数

最後は、引数を受け取り、返却値も返す関数です。
これはもっともよく使う形です。

宣言は次のようになります。

int func(int n);

このタイプは、受け取った値をもとに計算や判定を行い、その結果を返します。

シンプルな例

たとえば、渡された整数を2倍にして返す関数を考えてみます。

ファイル名:13_6_4.c

// 引数と返却値の両方を持つ関数の例
#include <stdio.h>

int double_value(int number);

int main(void)
{
    int value = 8;
    int result = double_value(value);

    printf("%dを2倍した値は%dです。\n", value, result);

    return 0;
}

// 受け取った値を2倍にして返す関数
int double_value(int number)
{
    return number * 2;
}

実行結果例

8を2倍した値は16です。

この関数の特徴

この関数は、

  • number という引数を受け取る
  • 計算結果を return で返す

という流れになっています。

そのため、呼び出し側は

int result = double_value(value);

のように、引数を渡して結果を受け取れます。

どんなときに使うのか

このタイプはとてもよく使われます。
たとえば、

  • 税込み金額を計算する
  • BMIを計算する
  • 最大値を求める
  • 判定結果を返す

など、入力をもとに結果を作る処理はこの形になることが多いです。

4つのパターンをまとめて比較する

ここまでの内容を、もう一度表で整理してみましょう。

パターン書き方呼び出し例主な使い方
引数なし・返却値なしvoid show(void);show();決まった処理だけ行う
引数あり・返却値なしvoid print_times(int n);print_times(3);受け取った値で表示や処理をする
引数なし・返却値ありint get_value(void);int x = get_value();値を返す
引数あり・返却値ありint calc(int n);int y = calc(10);計算や判定結果を返す

この4つを整理して考えるだけでも、関数の形をかなり選びやすくなります。

void の意味をもう少し丁寧に確認しよう

学習の初期段階で少し混乱しやすいのが、void が2か所に出てくることです。

たとえば、

void greet(void);

では、前と後ろの void は意味が少し違います。

位置意味
先頭の void返却値がない
丸かっこの中の void引数がない

つまりこの関数は、

  • 何も受け取らない
  • 何も返さない

関数です。

一方で、

int get_number(void);

なら、

  • int を返す
  • 引数は受け取らない

という意味になります。

この区別はとても大事なので、最初のうちにしっかり意識しておくとよいです。

関数をどう選べばよいのか

関数を作るときは、次の2つを自分に問いかけると考えやすいです。

値を受け取る必要があるか

処理の内容が毎回変わるなら、引数が必要になりやすいです。
たとえば、回数・金額・点数・半径などを使うなら、引数で渡すことが多いです。

結果を呼び出し元へ返す必要があるか

計算結果や判定結果を後で使いたいなら、返却値が必要になります。
逆に、表示だけして終わるなら返却値がいらないこともあります。

この2つで考えると、4つのパターンのどれを使うか決めやすくなります。

図で4つのパターンを整理する

この図では、関数に向かって入る矢印が引数、関数から出ていく矢印が返却値を表します。

  • 矢印が入らないなら引数なし
  • 矢印が出ないなら返却値なし
  • 両方あれば引数も返却値もある

というように見れば、4つの違いが直感的につかみやすくなります。

初心者が混乱しやすいポイント

関数の4つのパターンを学ぶとき、初心者が引っかかりやすいところを表で整理しておきます。

よくある混乱正しい考え方
void は何となく付けるものだと思うvoid は「ない」ことを明示する意味がある
引数がないなら丸かっこを空にすればよいと思う学習段階では void と明示するほうが分かりやすい
返却値がない関数でも return が必要だと思う最後まで到達すれば自動で戻る
返却値があるのに受け取らなくてもよいと思う受け取らないこともできるが、結果を使うなら変数などで受け取る
引数と返却値の違いが曖昧引数は受け取る値、返却値は返す値

このあたりを意識して読むだけでも、理解しやすさがかなり変わります。

サンプルを見分ける練習

次の宣言を見て、どのパターンかを判断できるようになると、とても強いです。

void show_menu(void);

これは、引数なし・返却値なし です。

void print_score(int score);

これは、引数あり・返却値なし です。

int get_today_number(void);

これは、引数なし・返却値あり です。

double calculate_area(double radius);

これは、引数あり・返却値あり です。

関数宣言を見た瞬間に、どのタイプか判断できるようになると、コードを読むのがかなり楽になります。

実践問題

次の4つの関数を作成し、それぞれの違いを確認してください。

① 引数も返却値も持たない関数を作成してください。

関数宣言

void show_title(void);

機能
画面にタイトルを表示する。

② 引数だけ持つ関数を作成してください。

関数宣言

void print_stars(int count);

機能

  • を count 個表示する。

③ 返却値だけ持つ関数を作成してください。

関数宣言

int get_base_number(void);

機能
固定の整数値 5 を返す。

④ 引数と返却値の両方を持つ関数を作成してください。

関数宣言

int multiply_by_two(int number);

機能
受け取った整数を2倍にして返す。

実行結果例

関数パターンの確認
*****
基準の数は5です。
2倍した値は10です。

解答例

ファイル名:13_6_5.c

// 関数の4つのパターンを確認するプログラム
#include <stdio.h>

void show_title(void);
void print_stars(int count);
int get_base_number(void);
int multiply_by_two(int number);

int main(void)
{
    int base;
    int result;

    show_title();
    print_stars(5);

    base = get_base_number();
    result = multiply_by_two(base);

    printf("基準の数は%dです。\n", base);
    printf("2倍した値は%dです。\n", result);

    return 0;
}

// タイトルを表示する関数
void show_title(void)
{
    printf("関数パターンの確認\n");
}

// * を指定回数表示する関数
void print_stars(int count)
{
    int i;

    for (i = 0; i < count; i++) {
        printf("*");
    }
    printf("\n");
}

// 基準となる整数値を返す関数
int get_base_number(void)
{
    return 5;
}

// 受け取った値を2倍にして返す関数
int multiply_by_two(int number)
{
    return number * 2;
}

解答例の見方

このプログラムには、4つのパターンがすべて入っています。

関数名パターン
show_title引数なし・返却値なし
print_stars引数あり・返却値なし
get_base_number引数なし・返却値あり
multiply_by_two引数あり・返却値あり

1つのプログラムの中で見比べると、それぞれの違いがかなりはっきり見えてきます。

学習のコツ

「関数の4つのパターン」を覚えるときは、丸暗記よりも役割と一緒に覚えるのがおすすめです。

  • 値を受け取らないなら引数なし
  • 結果を返さないなら返却値なし
  • 計算結果を使いたいなら返却値あり
  • 毎回違うデータで動かしたいなら引数あり

このように考えると、文法が単なる形ではなく、意味のある選択として見えてきます。

さらに、自分で関数を作るときに

「この関数は何を受け取る必要があるかな」
「この関数の結果は呼び出し元で使うかな」

と考える習慣をつけると、関数設計の力が少しずつ身についていきます。