トップC-Tips > 関数のプロトタイプ宣言

関数のプロトタイプ宣言

stdio.h、stdlib.hなどヘッダファイルと呼ばれるファイルには、 関数のプロトタイプ宣言、構造体の定義、定数の定義などが含まれている。

次のプログラムは tcc でコンパイルしても、gcc でコンパイルしても、 特に、エラーメッセージは出ない。

// protype01.c 2011-09-26
// 間違い探しプログラム
#include <stdio.h>

int main() {
    double v = atof("23.4");
    printf("v=%f\n", v);
}

このプログラムの実行結果を下に示す。

c:\MH\www\c-tips\c>prototype01
v=5310416.000000

おや! おかしいではないか。 この間違い探しは、初心者はちょっと時間がかかるかも知れない。 C言語では、使用する関数の引数のタイプや戻り値のタイプ(関数のプロトタイプと言う) をプログラムの先頭で宣言しておいた方が無難である。 標準ライブラリ関数については、この宣言はヘッダファイルに含まれているので、 しかるべきヘッダファイルをインクルードすればいい。

問題は関数のプロトタイプ宣言を忘れていても必ずしもコンパイルエラーメッセージが出ないことである。 引数の型のチェックは行われず、関数の戻り値はint型とみなされる。 戻り値は double 型であるのに、int型とみなされたため、おかしな結果となったわけである。

atof関数のプロトタイプ宣言は stdlib.h に次のように定義されている。

double      atof (const char*);
なお、ここで、引数に付けられた const は const修飾子と呼ぶ。 この引数で与えられた文字列を atof関数が変更することはない、ということを表す。

プログラムを

// protype02.c 2011-09-26
#include <stdio.h>
#include <stdlib.h>

int main() {
    double v = atof("23.4");
    printf("v=%f\n", v);
}
のように変更すれば、
c:\MH\www\c-tips\c>prototype02
v=23.400000
のように、正しい結果が得られる。

なお、この場合、stdlib.h で必要なのは、 atof関数のプロトタイプ宣言だけであるから、 次のようにしてもよい。

プロトタイプ宣言の引数名は省略することができる。すなわち、 double atof (const char*); でもよい。

// protype03.c 2012-09-08
double  atof (const char* str);

int main() {
    double v = atof("23.4");
    printf("v=%f\n", v);
}

printf関数については、 戻り値(返却値)を使うわけではないので、 プロトタイプ宣言がなくてもよい。ただし、 gcc では次に示すように警告が出るが、 正しくコンパイル・実行される。

しかし、stdio.h をインクルードしておく方が無難である。

c:\mh\www\c-tips\c>gcc prototype03.c
prototype03.c: In function 'main':
prototype03.c:8:5: warning: incompatible implicit declaration of built-in functi
on 'printf'

c:\mh\www\c-tips\c>a
v=23.400000