C言語の関数とは?基本から引数・戻り値まで初心者向けに解説

2025年4月14日月曜日

C言語

C言語の学習を進めると、避けては通れないのが関数です。最初は「なんだか小難しそう…」「なんでわざわざ使うの?」なんて思うかもしれませんね。

この記事を読めば、関数の基本的なことから、実際の使い方、ちょっとした注意点までバッチリ分かります。さあ、一緒にC言語の関数をマスターして、プログラミングをもっと楽しく、効率的にしちゃいましょう!

この記事で学べること

  • 関数がどんなもので、なぜプログラム作成に役立つのか
  • 関数の基本的な作り方(定義のしかた)
  • 関数をプログラム中で使う方法(呼び出し方)
  • 関数に情報を渡す「引数」と、関数から結果を受け取る「戻り値」の仕組み
  • 関数を使うときに気をつけるべき点

C言語の関数とは?プログラムを分かりやすく整理する考え方

C言語における関数とは、一連の処理をひとまとめにしたものです。例えば、画面にメッセージを表示する、二つの数字を足し算する、といった特定の作業を一つの「部品」として作っておくイメージです。

なぜ関数が役立つのでしょうか? プログラムが長くなったり複雑になったりすると、同じような処理をあちこちで書く必要が出てくることがあります。そんな時、関数としてまとめておけば、その処理が必要な時に「関数名」を呼び出すだけで済みます。

何度も同じコードを書かなくて良いので、タイプミスも減りますし、コード全体が短く、読みやすくなります。

料理で考えてみましょう。「野菜を切る」「お湯を沸かす」「炒める」といった作業をそれぞれ別の手順(関数)として覚えておけば、色々な料理(プログラム)を作る時に、手順を組み合わせるだけで済みますよね。関数も同じで、プログラムを小さな作業単位に分割して、管理しやすくするための仕組みなんです。

実は、皆さんがC言語で最初に書くであろう main というのも、特別な関数の一つなんですよ。プログラムは main 関数から実行が始まります。

C言語の関数の基本的な書き方(関数の定義)

では、実際にどうやって関数を作る(定義する)のか、その基本形を見てみましょう。関数は主に4つの部分から構成されます。

戻り値の型 関数名(仮引数リスト) {
    // ここに関数が行う処理を書く
    // 例: 計算したり、文字を表示したり

    return 戻り値; // 関数が何か結果を返す場合
}

それぞれの部分を分解してみましょう。

  • 戻り値の型
    • 関数が処理を終えた後に、どんな種類のデータ(結果)を返すかを指定します。整数なら int、何も返さないなら void などです。
  • 関数名
    • 関数を呼び出すときに使う名前です。どんな処理をするか分かりやすい名前を付けるのがおすすめです。
  • 仮引数リスト
    • 関数が処理を行うために外部から受け取る情報(データ)を指定します。(int a, int b) のように、型と名前のペアで書きます。情報を受け取らない場合は (void) または () と書きます。
  • 関数本体
    • { } で囲まれた部分で、実際に行う処理の命令を書きます。

例えば、二つの整数を受け取って、足し算した結果を返す関数は、こんな風に定義できます。

int add(int a, int b) { // int型の値を返し、int型の引数を2つ取るadd関数
    int sum; // 計算結果を入れるための変数
    sum = a + b;
    return sum; // 計算結果(sum)を返す
}

値を返さない(画面に何か表示するだけ、など)関数の場合は、戻り値の型を void にします。

void printHello(void) { // 何も返さず、引数も取らないprintHello関数
    printf("Hello!\n");
    // void型なので return 文は必須ではない
}

戻り値の型:関数が返す「結果」の種類

関数が処理を終えたときに、呼び出し元に「結果」として返すデータの種類を「戻り値の型」で示します。主な型には以下のようなものがあります。

  • int 整数(例 10, -5, 0)
  • float / double 小数(例 3.14, -0.5)
  • char 1文字(例 'a', 'B')
  • void 何も返さない

関数の中で計算した結果や、処理の成否などを呼び出し元に伝えたい場合に、return 文を使います。return 値; のように書くと、その「値」が関数の結果として返されます。例えば、return sum; であれば、変数 sum の中身が関数の結果となります。

void型は値を返さない関数の目印です。 void 型の関数の場合、return 文は書かなくても良いですし、書く場合は処理を途中で終了させる目的で return; のように値なしで記述します。

関数名:関数を呼び出すための「名前」

関数名は、その関数を識別し、呼び出すために使います。自分で関数を作る場合、自由に名前を付けられますが、いくつかルールと、分かりやすくするためのコツがあります。

ルールとしては、

  • 英数字とアンダースコア _ が使えます。
  • 最初の文字は英字かアンダースコアである必要があります(数字はダメ)。
  • intwhile のようなC言語のキーワード(予約語)は使えません。
  • 大文字と小文字は区別されます(addAdd は違う関数名とみなされます)。

そして、一番意識したいのは、関数が何をするのかが名前から推測できるようにすることです。

例えば、合計を計算するなら calculateSumaddNumbers、メッセージを表示するなら printMessage のような名前が良いでしょう。func1a のような名前は、後でコードを見返したときに「何をする関数だっけ?」となりがちです。

処理内容がわかる名前付けが、後々の自分を助けます。分かりやすい名前は、プログラム全体の読みやすさにも繋がります。

仮引数リスト:関数に渡す「情報」

関数が処理を行う際に、外部(呼び出し元)からデータを受け取りたい場合があります。その受け取るデータを入れるための「入り口」が「仮引数(かりひきすう)」です。関数定義の ( ) の中に、型名 変数名 の形で書きます。

// 例: 2つの整数を受け取る場合
int add(int number1, int number2) { ... }

// 例: 1つの小数を受け取る場合
void printFloat(float value) { ... }

複数の引数が必要な場合は、カンマ , で区切って記述します。仮引数で宣言された変数(上の例だと number1, number2, value)は、その関数の中だけで使うことができます。

もし、関数が外部から情報を受け取る必要がない場合は、( ) の中を空にするか、(void) と書きます。

どちらでも動作しますが、引数を取らないことを明確に示すために (void) と書く方が、より丁寧な書き方とされています。

// 引数を取らない関数の例
void sayGoodbye(void) { ... }

引数がない場合は ( ) の中を空にするか、(void) と書きます。

C言語の関数の使い方(関数の呼び出し)

関数を定義しただけでは、プログラム中でその処理は実行されません。定義した関数を使うには、「呼び出す」必要があります。関数の呼び出しはとてもシンプルです。

関数名(実引数リスト);

定義した「関数名」の後に ( ) を付け、もし関数が引数を必要とするなら、( ) の中に渡したい値(実引数)を書きます。複数の実引数がある場合は、カンマ , で区切ります。

例えば、先ほど定義した add 関数や printHello 関数を呼び出すには、以下のように書きます。

int main() {
    int result;

    // add関数を呼び出し、引数として 5 と 3 を渡す
    // 戻り値(計算結果)を変数 result で受け取る
    result = add(5, 3);

    printf("計算結果: %d\n", result); // result を表示

    // printHello関数を呼び出す (引数なし、戻り値なし)
    printHello();

    return 0;
}

ここで注意したいのが「仮引数」と「実引数」の違いです。

  • 仮引数 関数を定義するときに書く、値を受け取るための変数名 (例: int add(int a, int b)ab)。
  • 実引数 関数を呼び出すときに実際に渡す値や変数 (例: add(5, 3)53)。

関数が呼び出されると、実引数の値が仮引数にコピーされて、関数本体の処理が実行されます。add(5, 3) の呼び出しでは、a5 が、b3 が入った状態で add 関数の処理が始まるわけです。

戻り値がある関数の場合、その戻り値は呼び出し元の式の一部として使えます。result = add(5, 3); のように変数に代入したり、printf("答えは %d\n", add(10, 20)); のように直接別の関数の引数として使ったりもできます。

C言語の関数を使ったサンプルプログラム

さて、理屈は分かってきたところで、実際に動くプログラムを見てみましょう! ここでは、簡単な関数を2つ作り、それを main 関数から呼び出すサンプルを示します。

実際にコードを書いて、コンパイルして、実行してみるのが理解への一番の近道です。ぜひお手元の環境で試してみてくださいね。

サンプル1:2つの整数の合計を計算して返す関数

まずは、整数を2つ受け取って、その合計を計算して返す add 関数を使った例です。戻り値がある関数の典型的な使い方になります。

#include <stdio.h>

// ----- 関数の定義 ここから -----
// 機能:2つの整数 a と b を受け取り、その合計を返す
// 戻り値:int型 (合計値)
// 引数:int a (1つ目の整数), int b (2つ目の整数)
int add(int a, int b) {
    int sum = a + b; // a と b を足して変数 sum に入れる
    return sum;      // sum の値を返す
}
// ----- 関数の定義 ここまで -----

int main() {
    int num1 = 10;
    int num2 = 20;
    int answer; // 関数の戻り値を受け取るための変数

    // ----- 関数の呼び出し ここから -----
    // add関数を呼び出し、num1 と num2 を引数として渡す
    // add関数が返した値(計算結果)が answer に入る
    answer = add(num1, num2);
    // ----- 関数の呼び出し ここまで -----

    printf("%d + %d = %d\n", num1, num2, answer);

    // 直接、関数の呼び出し結果を printf の引数に使うこともできる
    printf("5 + 8 = %d\n", add(5, 8));

    return 0;
}

このコードをコンパイルして実行すると、次のような結果が表示されるはずです。

10 + 20 = 30
5 + 8 = 13

main 関数の中で add(num1, num2) と書くことで、add 関数が呼び出されています。num1 の値 10 が仮引数 a に、num2 の値 20 が仮引数 b に渡され、add 関数内で計算された結果 30return sum; によって返されます。return文で返された値が、呼び出し元の変数 answer に代入されています。 2回目の printf では、add(5, 8) の戻り値 13 が直接使われていますね。

サンプル2:メッセージを表示する関数 (戻り値なし)

次は、特定のメッセージを画面に表示するだけの、戻り値がない (void 型の) 関数 printMessage の例です。引数も受け取らないようにしてみましょう。

#include <stdio.h>

// ----- 関数の定義 ここから -----
// 機能:固定のメッセージを画面に表示する
// 戻り値:void (何も返さない)
// 引数:void (何も受け取らない)
void printMessage(void) {
    printf("Hello from the function!\n");
    // void型なので、return文は省略可能
}
// ----- 関数の定義 ここまで -----

int main() {
    printf("Calling the function first time...\n");
    // ----- 関数の呼び出し ここから -----
    printMessage(); // printMessage関数を呼び出す
    // ----- 関数の呼び出し ここまで -----

    printf("Calling the function second time...\n");
    // ----- 関数の呼び出し ここから -----
    printMessage(); // もう一度呼び出す (何度でもOK)
    // ----- 関数の呼び出し ここまで -----

    return 0;
}

実行結果は以下のようになります。

Calling the function first time...
Hello from the function!
Calling the function second time...
Hello from the function!

main 関数内で printMessage(); と書くことで、printMessage 関数が呼び出され、その中の printf 文が実行されています。void 型の関数は、何か値を返すわけではないので、answer = printMessage(); のように戻り値を受け取る書き方はできません(エラーになります)。void型の関数は、呼び出しても値が返ってこないので、変数で受け取ることはしません。 ただ処理を実行させたいだけの場合に便利です。

C言語の関数を使う上でのポイント・注意点

関数は非常に便利ですが、いくつか知っておくと良いポイントや、初心者がつまずきやすい注意点があります。ここでは特に「関数プロトタイプ宣言」と「変数のスコープ」について見ていきましょう。

関数プロトタイプ宣言:関数の「紹介状」

C言語では、基本的にプログラムは上から下に読まれて処理されます。もし、関数を呼び出すコードよりも「後」に、その関数の定義が書かれている場合、コンパイラ(プログラムを機械語に翻訳するやつ)は呼び出し時点で「そんな名前の関数、知らないよ?」となってしまい、エラーや警告を出すことがあります。

それを解決するのが「関数プロトタイプ宣言」です。これは、プログラムの(通常は)先頭の方で、「これから、こんな形の関数を使いますよ」と、事前に関数の名前、戻り値の型、引数の型リストだけをコンパイラに教えてあげる記述です。いわば、関数の「紹介状」のようなもの。

書き方は、関数定義の最初の行(ヘッダー)の最後にセミコロン ; を付けるだけです。

#include <stdio.h>

// ----- 関数プロトタイプ宣言 ここから -----
int add(int a, int b); // add関数のプロトタイプ宣言 (引数名は省略しても良い: int add(int, int);)
void printHello(void); // printHello関数のプロトタイプ宣言
// ----- 関数プロトタイプ宣言 ここまで -----

int main() {
    int sum = add(10, 5); // 定義は下にあるけど、宣言があるのでOK
    printf("Sum: %d\n", sum);

    printHello(); // 定義は下にあるけど、宣言があるのでOK

    return 0;
}

// ----- 関数の定義 ここから -----
// (main関数よりも後に定義を書いても大丈夫)
int add(int a, int b) {
    return a + b;
}

void printHello(void) {
    printf("Hello!\n");
}
// ----- 関数の定義 ここまで -----

このようにプロトタイプ宣言をしておけば、関数の定義が main 関数より後(あるいは別のファイル)にあっても、コンパイラは関数の形を認識できるので、問題なく呼び出すことができます。

関数定義をmain関数より後に書く場合、プロトタイプ宣言がないとコンパイラが関数の形を知らずエラーになることがあります。 多くの標準ライブラリ関数(printfなど)も、stdio.h といったヘッダーファイル内でプロトタイプ宣言されているからこそ、私達は定義を知らなくても使えるのです。

変数のスコープ:関数内で生まれた変数の寿命

関数の中で宣言された変数(これを「ローカル変数」と呼びます)は、原則として、その関数の中だけで有効です。関数の処理が終わると、そのローカル変数は消えてしまいます。これを変数の「スコープ(有効範囲)」と言います。

例えば、ある関数 myFunc の中で int count = 0; と宣言した場合、変数 countmyFunc{ } の中でしか使えません。main 関数や、他の関数から count 変数を直接参照したり、値を変更したりすることはできないのです。

#include <stdio.h>

void myFunction() {
    int localVar = 100; // myFunction のローカル変数
    printf("myFunctionの中: localVar = %d\n", localVar);
    // ここで localVar は使える
}

int main() {
    int mainVar = 50; // main のローカル変数
    printf("mainの中: mainVar = %d\n", mainVar);

    myFunction(); // myFunction を呼び出す

    // printf("mainからlocalVarを参照: %d\n", localVar); // エラー! localVarはここから見えない

    return 0;
}

もし最後のコメントアウトされた printf 文を実行しようとすると、コンパイル時に「localVar なんて変数は定義されていませんよ」というエラーが出ます。localVarmyFunction の「部屋」の中だけで使える道具であり、main 関数の「部屋」からは見えない、と考えれば分かりやすいかもしれません。

この仕組みがあるおかげで、関数ごとに独立して変数を使えるため、他の関数で同じ変数名を使っていたとしても、互いに影響を与えずに済みます。プログラム全体の見通しが良くなり、予期せぬバグを防ぐのに役立ちます。

関数内で宣言した変数は、基本的にその関数の { } の中でしか使えません。

まとめ

お疲れ様でした! 今回はC言語の関数の基本について、かなり詳しく見てきましたね。もう一度、ポイントをおさらいしておきましょう。

  • 関数は処理をまとめた「部品」で、コードの再利用性や可読性を高める。
  • 関数を作るには「定義」が必要で、戻り値の型、関数名、仮引数リスト、関数本体から成る。
  • 関数を使うには「呼び出し」が必要で、関数名と実引数を指定する。
  • 「引数」で関数に情報を渡し、「戻り値」で関数から結果を受け取れる (void型は返さない)。
  • 関数を呼び出す前に定義がない場合は「プロトタイプ宣言」が必要になることがある。
  • 関数内で宣言した変数(ローカル変数)は、その関数の中だけで有効(スコープ)。

関数を理解し、使いこなせるようになると、C言語でのプログラミングが格段に楽になりますし、作れるプログラムの幅も広がります。最初は少し戸惑うかもしれませんが、実際に自分で簡単な関数を作って動かしてみるのが一番です。


【関連記事】

>> C言語とは?特徴・できること・学ぶメリット

このブログを検索

  • ()

自己紹介

自分の写真
リモートワークでエンジニア兼Webディレクターとして活動しています。プログラミングやAIなど、日々の業務や学びの中で得た知識や気づきをわかりやすく発信し、これからITスキルを身につけたい人にも役立つ情報をお届けします。 note → https://note.com/yurufuri X → https://x.com/mnao111

QooQ