【问题标题】:error: conflicting types for 'f' and previous declaration of 'f' was here错误:“f”的冲突类型和“f”的先前声明在这里
【发布时间】:2012-02-17 06:33:19
【问题描述】:

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

我的c源代码:

/* test.c */

  1 #include<stdio.h>
  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<stdio.h>
      2 void f(struct node *k);
      3
      4 void f(struct node * k)
      5 {
      6
      7 }

gcc -c -w test.c

没有错误。

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

【问题讨论】:

  • 您使用的是什么版本的 GCC?对于 4.6.1,我在您的最后一个示例中也出现错误(原型和定义在同一个文件中) - 有或没有 extern

标签: c


【解决方案1】:

这与原型上的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++,则不会出现此问题。

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 嘿,我从标题中删除了 extern,但仍然得到相同的错误,另一件事,是由于函数参数 **struct node *k ** 导致的错误?在源代码和头文件中我都没有定义 **struct node ** ,它在不同的源代码中定义
    • 这很奇怪,尝试清理并重新编译。您所描述的不应导致相同的错误。此外,请始终包含使用它的结构定义...
    • 这有什么关系?我相信这个答案是不正确的。 6.2.2 “如果一个函数的标识符声明没有存储类说明符,它的链接被确定就像它是用存储类说明符 extern 声明的一样。如果一个对象的标识符声明具有文件范围并且没有存储类说明符,它的链接是外部的。”
    【解决方案3】:

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

    【讨论】:

    • 嘿,我从标题中删除了 extern,但仍然得到相同的错误,另一件事,是由于函数参数 **struct node *k ** 导致的错误?在源代码和头文件中我都没有定义 **struct node ** ,它在不同的源代码中定义
    • 在这种情况下,您需要将struct node 声明为extern。
    • 我需要在哪里声明它,意味着在 test2.h 或 test.c 中。只写下声明,我很困惑我需要声明什么。
    • 在 test2.h 添加extern struct node;.
    • 这是 test2.h:extern struct node; void f(struct node * k);
    猜你喜欢
    • 1970-01-01
    • 2011-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-09
    • 1970-01-01
    • 1970-01-01
    • 2021-09-05
    相关资源
    最近更新 更多