5

私のプログラムが2つのファイルで構成されている場合:

main.c

#include <stdio.h>

int main(void) { 
     printf("%lf\n",f());   
     return 0;
 }

func.c

double f(int a) {
 return 1;
}

コンパイラはエラーを表示しません。

プログラムが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

誰かがこの奇妙な行動を説明できますか?

4

3 に答える 3

6

Cは、関数にプロトタイプint func()があると想定します。特に指示がない限り(Cではint func();とint func(void);は異なることに注意してください)

2番目のケースでは、コンパイラーがプロトタイプを認識していない呼び出しを実行するf()ため、プロトタイプはであると見なされますint f();。後でf()、異なるプロトタイプを持つ定義を確認し、エラーを発行します。

1.ケースでは、コンパイルユニットが異なるため、これは発生しません。

于 2010-02-18T08:32:28.893 に答える
5

両方のプログラムが間違っています。

スコープ内にプロトタイプがない場合、コンパイラーは、関数が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は出力されませんでしたが、0が出力されました。これは、コンパイラががをf()返すと想定しint、割り当てがその「 」を。にd = f();変換したためです。コンパイラーは、コードが(暗黙的に)宣言された方法で定義されていないことを認識できなかったため、コードをコンパイルしました。しかし、上記のプログラムをコンパイルすることは標準では必要とされていないので、コンパイラはそれを拒否した可能性があります(たとえば試してみてください!)intdoublef()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番目のプログラムを拒否します。

于 2010-02-18T09:04:20.180 に答える
0

最初の例では使用しないので、定義がないためfunc.c、コンパイラが何をしているのか正確にはわかりません。f()

2番目の例では、シグネチャが異なる2つの関数を使用できない理由はわかりませんが、定義した関数を呼び出していません。f()引数なしで呼び出しますが、f定義するintは、別の関数にするintを取ります。

于 2010-02-18T08:34:50.557 に答える