next up previous contents
Next: 14.3 返り値または引数を持たない関数 Up: 14. 関数 III Previous: 14.1 関数の定義

14.2 関数の宣言

最初に述べたように、関数を作ったときに、積極的にコンパイラにその関数の 型や引数を教えてやれば、コンパイラはもし間違った関数の呼び出しをしたときに ちゃんとその旨を知らせてくれる。 このようにコンパイラに関数の仕様を知らせるために、関数の仕様を書く事を 関数の宣言という。関数の宣言は、ファイルの先頭、#include 文の後に 書いておくと良い。

 

関数の宣言は以下の書式で行う。

    [関数の型]  関数名( 引数の型 [,...]);

例
                test1();
        char    itoc(int);
        float   rmap1(int);
        float   test(int, char);
        char *  string();

勿論、関数の型(返り値の型)を省略すると整数型と解釈される。 特に、宣言は文なので、最後にセミコロン ; をつけることを忘れないように しなければならない。(この点で、関数の定義とは違う点に注意しよう。)

また、引数の型のみを記述しても良いが、引数を次のように書いても良い。分かり やすさから言えば、引数の変数も書いておく方が良いだろう。但し、その引数の変数名 は、完全なダミーで、まったく意味を持たない。

例
                test1();
        char    itoc(int num);
        float   rmap1(int a);
        float   test(int i, char c);
        char *  string();

  さてここで、関数の宣言がない場合の事を考えてみよう。関数の宣言がなく、 関数が使用される以前に関数が定義されている場合は、何の問題もない。 つまり、関数の定義でもって、関数の宣言となる。実は、以前の章で、我々が関数の 宣言なしで関数を定義しても大丈夫だったのは、このためである。では、逆に、 関数が宣言、定義される前に、関数が使用されたらどうなるのであろうか。 コンパイラは、その関数がどこか別のところ(例えば、標準ライブラリ)にある と考えるが、宣言はないので、整数型の関数だと決めつけてしまう。 すると、後からそれとは違う関数の宣言や定義を行っても、それは、既に あると考えられているので、2重に宣言・定義されていると見なされ、エラーに なる。また、整数型の関数ならば宣言せずに定義の前に引用しても良いが、 一般にはそうしたものはバグであることが多いので、コンパイラーは一応 警告(Warning) を出すので注意しよう。

コンパイルエラーになる例
#include <stdio.h>
main()
{
        test1(2,3);
}

char test1(int i, int j){
        printf("%d %d", i, j);
        return '!';
}

具体的なエラーメッセージは、今の場合、7行目の関数の定義がおかしいと思われて、

"test.c", line 7: identifier redeclared: test1
というエラーが出る。このエラーの意味は、test1 が2重に宣言されているという意味 である。

このエラーを回避するには、次のように関数を宣言しておくか、

コンパイルエラーにならない例1
#include <stdio.h>

char test1(int i, int j);    /* 関数宣言 */

main()
{
        test1(2,3);
}

char test1(int i, int j){
        printf("%d %d", i, j);
}

又は、次の例のように、関数が使用される前に、定義すれば良い。

コンパイルエラーにならない例2
#include <stdio.h>

char test1(int i, int j){
        printf("%d %d", i, j);
}

main()
{
        test1(2,3);
}

勿論、望ましいのは、例1の関数宣言を用いるほうである。



Noriyo Kanayama