【问题标题】:function declaration problem in multi file c project多文件c项目中的函数声明问题
【发布时间】:2020-06-23 05:30:47
【问题描述】:

我有一个项目,其中包含三个代码块中的文件:

main.c:

#include <stdio.h>
#include <conio.h>

int global = 10;

void f1(int);
void f1_1(int);
void f2(void);

int main()
{
    int x = 5;
    printf("inside main file");
    getch();
    f1(x);
    f2();
    getch();
    return 0;
}

file1.c:

#include <stdio.h>
#include <conio.h>

void f1(int x)
{
    printf("\ninside file1 >> f1 and x = %i", x);
    getch();
    f1_1(x);
}

void f1_1(int x)
{
    printf("\ninside file1 >> f1 >> f1_1 and x = %i", x);
    getch();
}

file2.c:

#include <stdio.h>
#include <conio.h>

extern int global;

void f2()
{
    printf("\ninside file2 >> f2 function , global var = %i", global);
    getch();
}

当我编译它时,我收到了这些警告:

c|8|警告:函数“f1_1”的隐式声明;你的意思是“f1”吗? [-Wimplicit-function-declaration]

c|11|警告:'f1_1' 的类型冲突

我该怎么办?

【问题讨论】:

  • 理想方式:将函数原型移动到不同的.h文件并包含在任何需要的地方,否则在f1之前定义f1_1
  • 请注意,在这种情况下,C 和 C++ 之间存在很大差异:在 C++ 中,您不会收到警告,而是收到错误。今后,请仅标记您正在使用的实际编程语言。

标签: c codeblocks


【解决方案1】:
void f1(int);
void f1_1(int);
void f2(void);

应该是:

extern void f1(int);
extern void f1_1(int);
extern void f2(void);

或者,正如@kiranBiradar 指出的那样,您可以在头文件中声明它们

file1.h

#pragma once
extern void f1(int);
extern void f1_1(int);

file2.h

#pragma once
extern void f2(void);


注意extern 关键字的使用。当您将文件中的函数前向声明为void f(void) 时,符号“f”是公共的,这意味着其他编译单元可以引用它。当您将其声明为 extern void f(void) 时,编译器不希望在该编译单元中定义该函数,而是将其留给链接器来查找该符号。

【讨论】:

    【解决方案2】:

    这是了解translation units这一重要概念的最佳时机。

    每个单独的源文件,连同所有包含的头文件,形成一个单独的翻译单元。每个翻译单元都是独立且不同的,并且独立编译,无需了解其他翻译单元。

    这意味着在例如声明的符号main.c 源文件在file1.c 源文件中将知道。

    当您编译 file1.c 时,编译器根本不知道您在 main.c 源文件中的 f1_1 函数声明,因此您会收到有关该事实的警告。

    要解决您的问题,您需要在file1.c 文件中声明f1_1 函数。通过添加前向声明(如 main.c 中的声明),或将 f1_1 的整个函数定义(实现)移到 f1 函数上方。

    或者您可以创建一个包含所有所需声明的头文件(对于f1f1_1f2 函数,以及 global 外部变量声明),并将这个头文件包含在你所有的源文件。如果您在多个翻译单元中使用多个符号(函数、变量等),则此解决方案效果最佳。

    我个人的建议是这样的:由于f1_1函数只在file1.c源文件内部使用,所以把它的定义移到f1上面,改成static。然后从main.c 源文件中删除它的声明。


    关于“隐式声明”和“冲突类型”警告,这是因为在旧的 C 标准中允许不声明函数,编译器会通过猜测基于声明的声明来创建 隐式声明在第一次调用函数时。

    猜测的重要部分是只有参数被猜测,返回类型总是int

    我不知道规范中关于这个的确切措辞,因为它在 C99 规范中被删除,但大多数编译器仍然允许这样做,只发出警告而不是错误。这是第一个警告的来源。

    但是,int 的返回类型仍在使用中。由于您的 f1_1 函数稍后在 file1.c 源文件中声明为返回 void,因此猜测的声明 (int f1_1(int)) 和实际声明 (void f1_1(int)) 之间存在不匹配,这会导致第二个警告.

    【讨论】:

      猜你喜欢
      • 2011-07-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多