【6日でできるC言語入門】プロトタイプ宣言

 C言語で本格的なプログラムを書いていくと、複数の関数を定義し、相互に呼び出しながら処理を進めることが一般的です。しかし、関数をどの順番で定義・記述すればいいのか悩む場面や、関数を呼び出す前に必ず定義を書かないとコンパイルエラーが出るといった問題に直面します。
 こうした問題を解決し、プログラムをすっきりと整理できる方法が「プロトタイプ宣言」です。プロトタイプ宣言は、関数の型や引数の情報を、先にコンパイラへ予告しておくための宣言です。
これにより、関数の定義をプログラムのどこに置いても、自由に呼び出すことができるようになります。

1.プロトタイプ宣言の基本

1.1. プロトタイプ宣言の書き方

プロトタイプ宣言は、関数本体の前に戻り値の型・関数名・引数の型だけを記述し、最後にセミコロン「;」を付けて書きます。
これは、関数の「最低限の仕様」をコンパイラに伝える役割があります。

項目内容の例
戻り値の型int, double, void など
関数名好きな名前(予約語は不可)
引数の型int, double など(複数可)

書式例

int sum(int, int);
double power(double, int);
void print_message(void);

1.2. プロトタイプ宣言を使ったプログラム例

 関数定義がプログラム後半にあっても、プロトタイプ宣言を先頭に書くことで自由に呼び出せます。

サンプルプログラム1(2つの整数の差を求める関数)

プロジェクト/ファイル名: Lesson38_1/main.c

#include <stdio.h>

// 関数diffのプロトタイプ宣言
int diff(int, int);

int main(void) {
    int x = 18, y = 7, result;

    result = diff(x, y);
    printf("差は %d です。\n", result);

    return 0;
}

// 2つの整数の差を返す関数
int diff(int a, int b) {
    return a - b;
}

実行結果

差は 11 です。

ポイント

  • int diff(int, int); のプロトタイプ宣言があることで、main関数の前にdiff関数を定義しなくてもOKです。

2.プロトタイプ宣言の必要性と利点

2.1. なぜプロトタイプ宣言が必要か

C言語のコンパイラは、ソースコードを上から順に解釈します。
 そのため、main関数の中などでまだ定義していない関数を呼び出すと、「その関数の型や引数が分からない」としてコンパイルエラーになります。
これを避けるには「呼び出す前に必ず定義を書く」必要がありますが、プロトタイプ宣言を使えば、呼び出し前に本体がなくても型情報を伝えられます。

プロトタイプ宣言がない場合のエラー例

※Visual Studio 2022 ではエラーとならない。

#include <stdio.h>

int main(void) {
    int value = multiply(3, 4); // まだmultiplyが定義されていないのでエラー
    printf("積は %d です。\n", value);
    return 0;
}

int multiply(int a, int b) {
    return a * b;
}

この場合、multiply の型や引数が分からないためエラーになります。

2.2. プロトタイプ宣言で解決

プロトタイプ宣言を先頭に加えることで、コンパイラは「このような関数が後から登場する」と理解し、エラーになりません。

プロジェクト/ファイル名: Lesson38_2/main.c

#include <stdio.h>

int multiply(int, int); // プロトタイプ宣言

int main(void) {
    int value = multiply(3, 4);
    printf("積は %d です。\n", value);
    return 0;
}

int multiply(int a, int b) {
    return a * b;
}

実行結果

積は 12 です。

3.複数の関数とプロトタイプ宣言

3.1. 相互に呼び出し合う関数

複雑なプログラムでは、関数同士が互いに呼び出し合うこともよくあります。この場合もプロトタイプ宣言が必須です。

サンプルプログラム2(2つの関数が相互呼び出し)

プロジェクト/ファイル名: Lesson38_3/main.c

#include <stdio.h>

void hello(void);
void world(void);

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

void hello(void) {
    printf("こんにちは、");
    world();
}

void world(void) {
    printf("世界!\n");
}

実行結果

こんにちは、世界!

ポイント

  • どちらの関数もプロトタイプ宣言しておくことで、定義の順序を気にせず相互に呼び出せます。

3.2. プロトタイプ宣言と引数名

プロトタイプ宣言では、引数の変数名は省略可能です。型だけ指定しておけば十分です。

宣言例意味
int func(int, double);型情報だけの宣言
int func(int num, double pi);変数名を付けてもOK

まとめ

  • プロトタイプ宣言は、関数の最低限の仕様(戻り値の型、関数名、引数の型)を事前に伝える仕組みです。
  • プログラムの先頭にプロトタイプ宣言を書いておけば、関数の定義や呼び出しの順序を自由にできるメリットがあります。
  • 実用的なプログラムや複数ファイルでの開発には、必ずプロトタイプ宣言を活用しましょう。