関数プロトタイプ宣言は忘るべからず

注意: この記事は1年以上前に掲載されたものです。情報が古い場合がありますのでお気を付け下さい。

C言語やC++でプログラミングを行う場合、関数のプロトタイプ宣言はちゃんと行わなければならない。さもないと深刻なバグに悩まされるかもしれない。

例えば以下のコードがある。

#include <stdio.h>

int main(void){
    printf("total: %d\n", total(1, 2));
    return 0;
}

int total(int a, int b) {
    return a + b;
}

上記のコードをコンパイルして出力した場合、total: 3と出力されるが、問題なのはC99以降でコンパイルした場合、以下のエラーあるいは警告が発生するのである。

Main.c:4:25: warning: implicit declaration of function 'total' is invalid in C99 [-Wimplicit-function-declaration]
    printf("total: %d", total(1, 2));
                        ^
1 warning generated.

上記の警告は「C99では暗黙の関数の宣言は無効です」という意味の警告である。

C99の仕様ではプロトタイプ宣言のなされていない関数はエラーが発生するが、int型に限ってはC90までの互換性のためかコンパイラーによっては警告となる場合も少なくない。

実際に、以下のようにfloat型に置き換えた場合は、コンパイルエラーに変わる。

#include <stdio.h>

int main(void){
    printf("total: %f", total(1, 2));
    return 0;
}

float total(float a, float b) {
    return a + b;
}

上記の場合は以下のコンパイルエラーが発生する。

Main.c:4:25: warning: implicit declaration of function 'total' is invalid in C99 [-Wimplicit-function-declaration]
    printf("total: %f", total(1, 2));
                        ^
Main.c:4:25: warning: format specifies type 'double' but the argument has type 'int' [-Wformat]
    printf("total: %f", total(1, 2));
                   ~~   ^~~~~~~~~~~
                   %d
Main.c:8:7: error: conflicting types for 'total'

うち、要注目なのが、totalという関数が実際にはfloat型で定義されているにもかかわらず、printf()内ではint型と解釈してしまい、型の間違いが発生してしまっているということである。

今回はC99で例に上げたため、このように警告及びエラーが出たが、C言語のコンパイラー及び仕様によっては暗黙的にint型として扱われたままコンパイルが通ってしまい、後に問題となる場合がある。

この場合、関数プロトタイプ宣言を行う必要がある。これは、実際の関数の定義を行う前に「こう言う関数があるよ」ということを宣言するものである。例えば、エラーが発生した2個目のコードを動かすためには、以下のようにすれば良い。

#include <stdio.h>

float total(float a, float b);

int main(void){
    printf("total: %f", total(1, 2));
    return 0;
}

float total(float a, float b) {
    return a + b;
}

上記のうち、int main(void)の前のfloat total(float a, float b);というのが関数プロトタイプ宣言である。

これで問題なくコンパイルが通り、total: 3.000000と出力されるようになる。

関数プロトタイプ宣言はC言語においてはかなり重要なファクターになるので、ぜひとも覚えておきたいところである。

タイトルとURLをコピーしました