プロトタイプのない古いスタイルの機能を備えたCコンパイラの動作
-
21-09-2019 - |
質問
ときに私のプログラムは、2つのファイルで構成されます:
main.cの
#include <stdio.h>
int main(void) {
printf("%lf\n",f());
return 0;
}
func.c
double f(int a) {
return 1;
}
コンパイラがすべてのエラーを表示しません。
私のプログラムは、一つだけのファイルで構成されている場合:
main.cの
#include <stdio.h>
int main(void) {
printf("%lf\n",f());
return 0;
}
double f(int a) {
return 1;
}
のVisual C ++ 2008コンパイラは次のエラーが表示されます:
Error 2 error C2371: 'f' : redefinition; different basic types d:\temp\projects\function1\function1\1.c 8 function1
缶誰でもこの奇妙な動作を説明する?
解決
両方のプログラムが間違っています。
範囲でプロトタイプがなければ、コンパイラは関数が返すint
ことを前提とパラメータの不特定多数をとる。
レッツ・チェンジファイルビットます:
$ cat func.c
double f(int a) {
return 1.0;
}
$ cat main.c
#include <stdio.h>
int main(void) {
double d = f();
printf("%lf\n", d);
return 0;
}
私はそれをコンパイルすると、は、gccが私(のVisual C ++、あまりにべき準拠モードで)警告します。しかし、のは、警告を無視しましょう。
$ gcc -std=c99 -pedantic -W -Wall func.c main.c -o test
func.c:1: warning: unused parameter 'a'
main.c: In function 'main':
main.c:4: warning: implicit declaration of function 'f'
$ ./test
0.000000
これは1を出力しなかったが、コンパイラはそのf()
がint
を戻し、割り当てd = f();
がint
にその「double
」に変換仮定ので0印刷です。それはf()
はそれがあった方法で定義されていなかった言うことができなかったため、コンパイラは、まだコードをコンパイルした(暗黙的に)宣言しました。コンパイラは(例えばgcc -Werror
で試して!)、それを拒否したことができるように
私たちは1つのファイルにすべてを持っている場合:
$ cat func.c >>main.c
$ gcc -std=c99 -pedantic -W -Wall func.c main.c -o test
main.c:4: warning: implicit declaration of function 'f'
main.c: At top level:
main.c:9: error: conflicting types for 'f'
main.c:4: error: previous implicit declaration of 'f' was here
main.c:9: warning: unused parameter 'a'
今のコンパイラは、紛争を見て、あなたにエラーメッセージが表示されます。しかし、コンパイラは、上記のプログラムを拒否するために必要とされていないことかもしれたりしないことがあります。
あなたが別の翻訳単位かどうかの関数f()
の正しい定義を持っている場合、彼らは知らないので、ほとんどのコンパイラは、最初のプログラムを拒否しないでください。彼らがそうしないことの知っているので、彼らは、第2のプログラムを拒否します。
他のヒント
C)は関数(プロトタイプint funcを有していると仮定します。あなたはそれ以外の場合に語っていない限り。(Cのint型のFUNC()に注意することを;とint型のFUNC(無効);異なるものです)
は2番目のケースでは、あなたはそれがf()
であると仮定して、コンパイラは、任意のプロトタイプを見ていないいるint f();
への呼び出しを行います。その後、その上には別のプロトタイプを持っているf()
ためのあなたの定義を見て - 。そして問題のエラー
これは、1の場合には発生しません。
あなたの最初の例は、func.c
を使用したことがない私はそれが何の定義がないため、コンパイラはf()
についてやっている正確に何かわからないようにします。
は、私は知りませんが、あなたは、あなたが定義した関数を呼び出すされていません。あなたは、引数なしでf()
を呼び出していますが、定義f
は異なる機能になりint型をとります。