C 言語関数マスター: 再帰とインライン関数の実践例
C 言語における関数とは?
C 言語の関数 は、プログラムを理解しやすく、テストしやすく、呼び出し側を変更せずに修正できる再利用可能なコードブロックです。関数はコードを分割し、プログラムをモジュール化することで、より良い効果的な結果をもたらします。簡単に言えば、大きなプログラムをさまざまな副プログラム (関数) に分割することです。

大きなプログラムをさまざまな関数に分割すると、各関数を個別に管理しやすくなります。プログラムでエラーが発生したとき、問題のある関数を容易に特定し、そのエラーのみを修正できます。必要なときにいつでも関数を呼び出して使用できるため、時間とスペースの節約につながります。
このチュートリアルでは以下を学習します:
- ライブラリ関数 vs ユーザー定義関数
- 関数宣言
- 関数定義
- 関数呼び出し
- 関数引数
- 変数のスコープ
- static 変数
- 再帰関数
- インライン関数
ライブラリ関数 vs ユーザー定義関数
すべての C プログラムには少なくとも 1 つの関数、すなわち main 関数がありますが、任意の数の関数を持てます。main() 関数はプログラムの開始点です。
C 言語では関数は 2 種類に分類されます:
- ライブラリ関数
- ユーザー定義関数
ライブラリ関数とユーザー定義関数の違いは、ライブラリ関数のコードを書く必要がない点です。プログラムの冒頭で常にインクルードするヘッダーファイル内にすでに存在します。関数名を正しい構文で記述するだけで使用できます。printf、scanf がライブラリ関数の例です。
一方、ユーザー定義関数は関数本体を自分で記述し、プログラムで操作が必要なときに呼び出すタイプの関数です。
ユーザー定義関数は常にユーザーによって書かれますが、後から C ライブラリの一部になることもあります。これは C プログラミングの大きな利点です。
C プログラミング関数は以下の 3 つの活動に分かれます:
- 関数宣言
- 関数定義
- 関数呼び出し
関数宣言
関数宣言とは関数名を書くことです。コードで関数を使用するための必須部分です。関数宣言では、プログラムで使用する関数名を変数宣言のように指定します。宣言されていない関数は使用できません。関数宣言は「関数 プロトタイプ」とも呼ばれます。
関数宣言 (プロトタイプ) は通常 main() 関数の上部で行われ、一般形は以下の通り:
return_data_type function_name (data_type arguments);
- return_data_type: 関数が呼び出し元に返す値のデータ型。
- function_name: 関数名に続けて括弧。
- Arguments: 引数名とそのデータ型宣言を括弧内に任意で配置。
整数変数の立方を計算する cube 関数の宣言例を示します:
#include <stdio.h>
/* 関数宣言 */
int add(int a, b);
/* 関数宣言終了 */
int main() {
関数が必ずしも値を返すとは限りません。その場合はキーワード void を使用します。
例: output_message 関数宣言は値を返さないことを示します: void output_message();
関数定義
関数定義とは関数本体を書くことです。関数本体は特定のタスクを実行する文で構成されます。単一の文または文ブロックで構成されます。これも関数の必須部分です。
int add(int a, int b) // 関数本体
{
int c;
c = a + b;
return c;
}
関数呼び出し
関数呼び出しとは、プログラムで必要なときに関数を呼び出すことです。関数を呼び出すと、その関数が設計された操作を実行します。関数呼び出しはプログラムのオプション部分です。
result = add(4, 5);
完全なコード例:
#include <stdio.h>
int add(int a, int b); // 関数宣言
int main() {
int a = 10, b = 20;
int c = add(10, 20); // 関数呼び出し
printf("Addition:%d\n", c);
getch();
}
int add(int a, int b) // 関数本体
{
int c;
c = a + b;
return c;
}
出力:
Addition:30
関数引数
関数の引数は、関数呼び出しによって必要な値を受け取るために使用されます。位置によって対応付けられ、最初の引数が最初のパラメータに、2 番目が 2 番目のパラメータに渡されます。
デフォルトでは 値渡し であり、データのコピーが呼び出された関数に渡されます。実際に渡された変数は変更されません。
値渡しを示すプログラム:
int add(int x, int y);
int main() {
int a, b, result;
a = 5;
b = 10;
result = add(a, b);
printf("%d + %d = %d\n", a, b, result);
return 0;
}
int add(int x, int y) {
x += y;
return x;
}
プログラム出力:
5 + 10 = 15
a と b の値は変更されていません。値のみがパラメータ x に渡されたためです。
変数のスコープ
変数スコープとは、プログラムコード内での変数の可視性を意味します。
C では、関数内で宣言された変数はそのコードブロックにローカルであり、関数外部から参照できません。一方、すべての関数の外部で宣言された変数はグローバルであり、プログラム全体からアクセス可能です。プログラム冒頭で #define で宣言された定数もプログラム全体からアクセス可能です。以下のプログラムは main とユーザー定義関数の両方からグローバル変数の値を出力します:
#include <stdio.h>
int global = 1348;
void test();
int main() {
printf("from the main function : global =%d \n", global);
test();
return 0;
}
void test() {
printf("from user defined function : global =%d \n", global);
}
結果:
from the main function : global =1348 from user defined function : global =1348
プログラム詳細の説明:

- 整数グローバル変数を 1348 で初期化して宣言。
- 引数を取らず値も返さない test() 関数を宣言・定義。グローバル変数値を出力して、グローバル変数がどこからでもアクセス可能であることを実証。
main関数内でグローバル変数を出力。- test 関数を呼び出してグローバル変数値を出力。
C では、引数が関数パラメータに渡されると、パラメータはローカル変数として振る舞い、関数終了時に破棄されます。
グローバル変数を使用する際は注意が必要です。どこからでも変更可能でエラーの原因になり得ます。使用前に初期化すべきです。
static 変数
static 変数はローカルスコープを持ちますが、関数終了時に破棄されません。したがって、static 変数は永遠に値を保持し、関数が再入力されるとアクセス可能になります。static 変数は宣言時に初期化され、static プレフィックスが必要です。
static 変数を使用するプログラム:
#include <stdio.h>
void say_hi();
int main() {
int i;
for (i = 0; i < 5; i++) {
say_hi();
}
return 0;
}
void say_hi() {
static int calls_number = 1;
printf("Hi number %d\n", calls_number);
calls_number++;
}
プログラム出力:
Hi number 1 Hi number 2 Hi number 3 Hi number 4 Hi number 5
再帰関数
数値の階乗を考えます。6! = 6 * 5 * 4 * 3 * 2 * 1 と計算されます。
この計算は fact * (fact - 1) を fact が 1 になるまで繰り返し計算することで行われます。
再帰関数とは、自分自身を呼び出し、再帰呼び出しを終了させるための終了条件 (ベースケース) を含む関数です。階乗計算の場合、終了条件は fact == 1 です。再帰は終了条件が真になるまで呼び出しを「スタック」することで機能します。
例:
#include <stdio.h>
int factorial(int number);
int main() {
int x = 6;
printf("The factorial of %d is %d\n", x, factorial(x));
return 0;
}
int factorial(int number) {
if (number == 1) return (1); /* 終了条件 */
else return (number * factorial(number - 1));
}
プログラム出力:
The factorial of 6 is 720
プログラム詳細の説明:

- 整数パラメータを取り、その階乗を返す再帰 factorial 関数を宣言。自身を呼び出し、ベースケースに達するまで数を減らし続ける。条件が真になると、それまでに生成された値が相乗され、最終的な階乗値が返される。
- 整数変数を値 "6" で宣言・初期化し、factorial 関数を呼び出してその階乗値を出力。
再帰メカニズムをより理解するためのチャート (関数が自身を呼び出し、ベースケースに達するまで続き、その後前の値を収集していく様子):

インライン関数
C プログラミングの関数は、最も頻繁に使用される命令を格納するために用いられ、プログラムのモジュール化に役立ちます。
関数が呼び出されると、命令ポインタが関数定義にジャンプします。関数実行後、命令ポインタはジャンプ元の文に戻ります。
関数を使用するたびに、関数定義にジャンプして戻るための余分なポインタヘッドが必要になります。これを不要にするのがインライン関数です。
インライン関数では、関数呼び出しが実際のプログラムコードに直接置き換えられます。すべての操作がインライン関数内で行われるため、どのブロックにもジャンプしません。
インライン関数は主に小規模な計算に使用され、大規模な計算には適しません。
インライン関数は通常の関数と似ていますが、関数名の前にキーワード inline を置きます。インライン関数は以下の構文で作成されます:
inline function_name() {
// 関数定義
}
インライン関数を実装するプログラムを作成:
inline int add(int a, int b) // インライン関数宣言
{
return (a + b);
}
int main() {
int c = add(10, 20);
printf("Addition:%d\n", c);
getch();
}
出力:
Addition: 30
上記プログラムは 2 つの数の加算にインライン関数を使用する例です。ご覧のように、インライン関数内で 2 数の加算を返すだけで、余分な行を書いていません。関数呼び出し時には加算したい値を渡しただけです。
まとめ
- 関数はミニプログラムまたは副プログラム。
- 関数はプログラムをモジュール化するために使用。
- ライブラリ関数とユーザー定義関数の 2 種類。
- 関数は宣言、関数本体、関数呼び出しで構成。
- 関数宣言と本体は必須。
- 関数呼び出しはプログラムでオプション。
- C プログラムには最低 1 つの関数 (main 関数) が存在。
- 各関数には名前、戻り値のデータ型 (または void)、パラメータがある。
- すべての関数は C プログラムで定義・宣言する必要がある。
- C 関数内の通常変数は関数呼び出し終了とともに即座に破棄されることを覚えておく。
- 関数に渡される引数は値渡しであり、アドレス渡しではないため変更されない。
- 変数スコープとはプログラム内での変数の可視性を指す。
- C プログラミングにはグローバル変数とローカル変数が存在。
C言語
- C++配列を関数に渡す完全ガイド:1次元・多次元配列の実例付き
- C言語ユーザー定義関数の4つの実証済みパターン
- C++ do-while文:構文、実践例、ネストしたループ
- C++演算子オーバーロード:コード例付き実践ガイド
- C++関数を実例で徹底解説:基本から応用まで
- C言語のcalloc():ゼロ初期化メモリ割り当てと実践例
- C言語の関数マスター:構造、宣言、ベストプラクティス
- Verilog関数のマスター:効率的なRTL設計のために
- Pythonラムダ関数をマスターする:実例とベストプラクティス
- Python round()関数を実例で徹底解説
- Python map()関数をマスター:構文、例、ベストプラクティス