错误:’f’的冲突类型和’f’的先前声明在这里

这段代码只是我在实际代码中发现的一个非常大的情况,所以我给出了这个。 在此代码中,结构“struct node”未定义,它在另一个c源文件中定义。

我的源代码:

/* test.c */ 1 #include 2 #include "test2.h" 3 4 void f(struct node * k) 5 { 6 7 } 

我的头文件:

 /* test2.h */ 1 extern void f(struct node * k); 

当我用gcc编译这段代码来创建一个目标文件时:

 gcc -w -c test.c 

我明白了:

 test.c:6: error: conflicting types for 'f' test2.h:1: error: previous declaration of 'f' was here 

我已经给出了函数f()的完整原型。 为什么我收到此错误?

另一件事是,当我在test.c中没有包含头文件test2.h并test.c中显式声明函数原型时,它会成功编译。 代码如下:

  /* test.c */ 1 #include 2 void f(struct node *k); 3 4 void f(struct node * k) 5 { 6 7 } 

gcc -c -w test.c

没错。

你能解释为什么这次我没有收到错误吗?

这与原型上的extern关键字无关(尽管没有必要)。

您需要struct node的前向声明:

 /* test2.h */ struct node; // <== this extern void f(struct node * k); 

如果没有前向声明,函数原型中的struct node对于该特定函数原型是本地的

因此,当编译器看到f()的定义时,它还会看到struct node另一个不同的本地声明,并认为你对f()有一个冲突的声明。

见C99 6.9.1“标识符范围”:

对于标识符指定的每个不同实体,标识符仅在称为其范围的程序文本的区域内可见(即,可以使用)。 由相同标识符指定的不同实体具有不同的范围,或者在不同的名称空间中。 范围有四种:函数,文件,块和函数原型。 (函数原型是声明其参数类型的函数的声明。)

...

如果声明标识符的声明符或类型说明符出现在函数原型(不是函数定义的一部分)的参数声明列表中,则标识符具有函数原型作用域,该作用域终止于函数声明符的末尾。

GCC 4.6.1为我提供了一个很好的警告:

 C:\temp\test.c:3:22: warning: 'struct node' declared inside parameter list [enabled by default] C:\temp\test.c:3:22: warning: its scope is only this definition or declaration, which is probably not what you want [enabled by default] 

C ++使函数原型范围仅适用于参数名称(C ++ 03 3.3.3),因此如果将代码编译为C ++,则不会看到此问题。

从标题中删除extern。 当您将函数声明为外部函数时,指导编译器不会编译该函数,并且将在链接中解析对该函数的任何引用。 通常,此声明在使用预编译库时完成。

在你的test2.h中你已经将f声明为extern ,这就是你得到错误的原因。 在test.c中,原型中没有extern声明。