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)char1文字(例 'a', 'B')void何も返さない
関数の中で計算した結果や、処理の成否などを呼び出し元に伝えたい場合に、return 文を使います。return 値; のように書くと、その「値」が関数の結果として返されます。例えば、return sum; であれば、変数 sum の中身が関数の結果となります。
void型は値を返さない関数の目印です。 void 型の関数の場合、return 文は書かなくても良いですし、書く場合は処理を途中で終了させる目的で return; のように値なしで記述します。
関数名:関数を呼び出すための「名前」
関数名は、その関数を識別し、呼び出すために使います。自分で関数を作る場合、自由に名前を付けられますが、いくつかルールと、分かりやすくするためのコツがあります。
ルールとしては、
- 英数字とアンダースコア
_が使えます。 - 最初の文字は英字かアンダースコアである必要があります(数字はダメ)。
intやwhileのようなC言語のキーワード(予約語)は使えません。- 大文字と小文字は区別されます(
addとAddは違う関数名とみなされます)。
そして、一番意識したいのは、関数が何をするのかが名前から推測できるようにすることです。
例えば、合計を計算するなら calculateSum や addNumbers、メッセージを表示するなら printMessage のような名前が良いでしょう。func1 や a のような名前は、後でコードを見返したときに「何をする関数だっけ?」となりがちです。
処理内容がわかる名前付けが、後々の自分を助けます。分かりやすい名前は、プログラム全体の読みやすさにも繋がります。
仮引数リスト:関数に渡す「情報」
関数が処理を行う際に、外部(呼び出し元)からデータを受け取りたい場合があります。その受け取るデータを入れるための「入り口」が「仮引数(かりひきすう)」です。関数定義の ( ) の中に、型名 変数名 の形で書きます。
// 例: 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)のaとb)。 - 実引数 関数を呼び出すときに実際に渡す値や変数 (例:
add(5, 3)の5と3)。
関数が呼び出されると、実引数の値が仮引数にコピーされて、関数本体の処理が実行されます。add(5, 3) の呼び出しでは、a に 5 が、b に 3 が入った状態で 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 関数内で計算された結果 30 が return 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; と宣言した場合、変数 count は myFunc の { } の中でしか使えません。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 なんて変数は定義されていませんよ」というエラーが出ます。localVar は myFunction の「部屋」の中だけで使える道具であり、main 関数の「部屋」からは見えない、と考えれば分かりやすいかもしれません。
この仕組みがあるおかげで、関数ごとに独立して変数を使えるため、他の関数で同じ変数名を使っていたとしても、互いに影響を与えずに済みます。プログラム全体の見通しが良くなり、予期せぬバグを防ぐのに役立ちます。
関数内で宣言した変数は、基本的にその関数の { } の中でしか使えません。
まとめ
お疲れ様でした! 今回はC言語の関数の基本について、かなり詳しく見てきましたね。もう一度、ポイントをおさらいしておきましょう。
- 関数は処理をまとめた「部品」で、コードの再利用性や可読性を高める。
- 関数を作るには「定義」が必要で、戻り値の型、関数名、仮引数リスト、関数本体から成る。
- 関数を使うには「呼び出し」が必要で、関数名と実引数を指定する。
- 「引数」で関数に情報を渡し、「戻り値」で関数から結果を受け取れる (
void型は返さない)。 - 関数を呼び出す前に定義がない場合は「プロトタイプ宣言」が必要になることがある。
- 関数内で宣言した変数(ローカル変数)は、その関数の中だけで有効(スコープ)。
関数を理解し、使いこなせるようになると、C言語でのプログラミングが格段に楽になりますし、作れるプログラムの幅も広がります。最初は少し戸惑うかもしれませんが、実際に自分で簡単な関数を作って動かしてみるのが一番です。
【関連記事】


0 件のコメント:
コメントを投稿
注: コメントを投稿できるのは、このブログのメンバーだけです。