プロトタイプ宣言

C言語でmain関数から別の関数を呼ぶ場合を考えよう。 以下は、二つの整数(int)の平均値を求めるつもりのプログラムである。

ave1.c

#include <stdio.h>

int main()
{
  int a = 5;
  int b = 4;
  printf("%d と %d の平均は %f です\n", a, b, average_int(a, b));
}

float average_int(int x, int y)
{
  float m;
  m = (x+y)/2.0;
  return m;
}

このプログラム ave1.c を保存しコンパイルしてみよう。

gcc -o ave1 ave1.c
ave1.c:11: warning: type mismatch with previous implicit declaration
ave1.c:7: warning: previous implicit declaration of `average_int'
ave1.c:11: warning: `average_int' was previously implicitly declared to return `int'

なにやら怪しいメッセージが出るはずだが、これらは全て warning(警告)なので、コンパイルが完了し実行ファイルはできている。 ところが実行すると結果がおかしい。

./ave1
5 と 4 の平均は 0.000000 です

警告メッセージをちゃんと読むとこの間違いの原因が分かる。

これは、main 関数の中で何の前ぶれもなく average_int を使うと、

特にことわりがなければ結果はintだな

という前提の元でコンパイルが進む。ところが実際は、 average_int 関数が返すのは float 型なので main関数で思っているのとは食い違いが生じて正しい結果が得られない。 これを直すには、

  1. main関数の中で average_int を呼ぶ前に、 average_intfloat型であると宣言する
  2. average_int 関数を main 関数より先に定義 する

のいずれかの方法を取ると良い。

1番は、以下のようにする。

ave2.c

#include <stdio.h>

int main()
{
  float average_int(int, int);
  int a = 5;
  int b = 4;
  printf("%d と %d の平均は %f です\n", a, b, average_int(a, b));
}

float average_int(int x, int y)
{
  float m;
  m = (x+y)/2.0;
  return m;
}

追加した部分

float average_int(int, int);

は、「average_int は、二つの引数として intint を取り、結果として float を返す」という宣言である。

このように、あとで利用する関数について、その引数の個数と型、 返す結果の型を宣言するものを、関数のプロトタイプ宣言という。 引数の部分には型だけ書いて、実際の変数名は書かなくて良いことに注意する。

C言語プログラミングでは、一つのファイルには全ての関数定義を書かない ことの方が多いので、プロトタイプ宣言は重要である。

もしプログラムを一つのソースファイルで書く場合は、 2番の方法で書いても良い。その場合は以下のようになる。

ave3.c

#include <stdio.h>

float avarage_int(int x, int y)
{
  float m;
  m = (x+y)/2.0;
  return m;
}

int main()
{
  int a = 5;
  int b = 4;
  printf("%d と %d の平均は %f です\n", a, b, avarage_int(a, b));
}

目次