
C言語入門|仮引数と実引数のしくみ
引数を使った関数呼び出し、
だいぶ慣れてきましたね。
でも、ここで一度、
ちょっと立ち止まって考えてみましょう。
「関数を定義するときの引数」と
「関数を呼び出すときの引数」
— 見た目はそっくりですが、
実は役割がまったく違う のです。
この違いを理解できるかどうかで、
今後の関数理解が一段深くなります。

同じカッコでも中身は別モノ
まずは、関数定義と関数呼び出しを並べて見てみましょう。
void showMessage(int level)
{
printf("レベル %d の処理です\n", level);
}
int main(void)
{
showMessage(3);
return 0;
}どちらも関数名の後ろにカッコがありますね。
でも実は、
- 定義側の引数
- 呼び出し側の引数
は、役割も意味も違います。
仮引数とは何か
関数定義に書く引数は、
仮引数(かりひきすう) と呼ばれます。
void showMessage(int level)この1行は、
関数がこんな自己紹介をしているイメージです。
私を呼び出すときは、
int 型の情報を1つ持ってきてください。
関数の中では level という名前で使います。
仮引数は、
- データ型
- 関数内で使う変数名
を決めているだけで、
実際の値はまだ決まっていません。
関数が呼び出されるその瞬間まで、
中身は空っぽの箱なのです。
実引数とは何か
一方、関数を呼び出す側で書く引数は、
実引数(じつひきすう) と呼ばれます。
showMessage(3);ここで指定している 3 は、
- 実際に使ってほしい具体的な値
- 関数に仕事を依頼するための材料
です。
実引数は、
この値を使って処理してください
という、
具体的な指示そのもの になります。
仮引数と実引数の対応関係
仮引数と実引数は、
関数が呼び出された瞬間に
次のように結びつきます。
| 種類 | 書かれる場所 | 役割 |
|---|---|---|
| 仮引数 | 関数定義 | 受け取る箱を用意する |
| 実引数 | 関数呼び出し | 実際の値を渡す |
今回の例では、
- 実引数 3
- 仮引数 level
が対応し、
関数内では level に 3 が代入された状態で
処理が始まります。
流れで考える仮引数と実引数
イメージとしては、
次のような流れです。
- main関数が値を準備する
- 関数を呼び出す
- 実引数の値が仮引数の箱に入る
- 関数内で処理が行われる
仮引数は「受け取り口」、
実引数は「渡される荷物」
と考えると、とてもわかりやすくなります。
仮引数がない関数では void を書く
引数を受け取らない関数もあります。
その場合、
仮引数がないことを明確に示すために
void を書く必要があります。
void greet(void)
{
printf("おはようございます\n");
}この void は、
- 引数は1つも受け取りません
という意思表示です。
void を省略してはいけない理由
うっかり次のように書いてしまうことがあります。
void greet()
{
printf("おはようございます\n");
}このコードは、
- コンパイルできる
- 実行もできる
ため、一見問題なさそうに見えます。
しかし、実はかなり危険です。
void を省略するリスク
void を省略すると、
次のような問題が起こる可能性があります。
| 問題点 | 内容 |
|---|---|
| 規格差 | Cの仕様によってはエラーや警告になる。 |
| 意味の曖昧さ | 任意個数の引数を許す意図と解釈される。 |
| 型チェック不能 | 引数の誤りをコンパイル時に検出できない。 |
特に、
プロトタイプ宣言で void を省略すると、
- 引数チェックが行われない。
- バグが静かに紛れ込む。
という、
非常にリスクの高いコード になります。
仮引数と実引数を意識する意味
仮引数と実引数を
しっかり区別して考えられるようになると、
- 関数の設計が明確になる。
- 引数ミスの原因がすぐわかる。
- 他人のコードも読みやすくなる。
といったメリットがあります。
関数を書くときは、
- 定義する立場
- 呼び出す立場
この2つを常に意識してみてください。
まとめ:名前は似ているが役割は別
最後にポイントを整理します。
| 用語 | 役割 |
|---|---|
| 仮引数 | 関数が受け取るための箱 |
| 実引数 | 呼び出し側が渡す具体的な値 |
| void | 引数がないことの明示 |
このしくみを理解できると、
次に学ぶ 値の受け渡し や
ポインタ引数 への理解も
ぐっと楽になります。
