隐式声明函数,无论标头 include 和 ifndef 如何

Bad*_*dda 3 c eclipse include-path implicit-declaration

我有众所周知的错误:

implicit declaration of function 'STLINKReadSytemCalls' [-Wimplicit-function-declaration]
implicit declaration of function 'printf' [-Wimplicit-function-declaration]
incompatible implicit declaration of built-in function 'printf'

Eclipse(更准确地说是 Atollic TrueStudio)友好地补充道:

include '<stdio.h>' or provide a declaration of 'printf'

阅读了数十亿篇关于如何解决这个问题的帖子,似乎三个问题可能会导致这些错误:

  • 函数定义在main之后;
  • 包含使用函数所需的标头
  • #ifndef#define并且#endif没有正确包装头文件

我发现一个帖子,其中有人似乎有这个错误,并在修复它后说 Eclipse 是问题所在。虽然找不到主题,但他的解决方案对我不起作用。这就像单击函数,source -> addincludes

主程序

int main(void) {

    if (STLINKReadSytemCalls() == 1)
        printf("Error in system calls.\n");
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

文件处理.c

#include "../header/fileProcessing.h"

int STLINKReadSytemCalls(void) {

    // mainly system calls
}
Run Code Online (Sandbox Code Playgroud)

文件处理.h

#ifndef FILEPROCESSING_H_
#define FILEPROCESSING_H_

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int STLINKReadSytemCalls(void);

#endif /* FILEPROCESSING_H_ */
Run Code Online (Sandbox Code Playgroud)

最令人困惑的部分是代码实际上是有效的。我有以下输出:

STM32 ST-LINK CLI v3.0.0.0
STM32 ST-LINK Command Line Interface

No ST-LINK detected
Unable to connect to ST-LINK!
Error in system calls.
Run Code Online (Sandbox Code Playgroud)

一切似乎都很好,但编译器一直在喊叫。如果需要,我将添加函数的主体,但我没有看到任何线索表明函数的主体可能会导致包含错误。我一定错过了一些如此明显的东西,以至于当我看到它时,我会像从来没有人那样捂脸;但我已经花了几个小时了,我对这显而易见的希望越来越渺茫。

哦,昨天使用相同的包含路径和相同的目录构建,它工作得很好。我真的不知道从那以后发生了什么变化。

unw*_*ind 5

你没有表明你的main.c文件有两个相当明显的

#include <stdio.h>
#include "../header/fileProcessing.h"
Run Code Online (Sandbox Code Playgroud)

线条,是故意的吗?否则我想这就是答案。

  • @Badda,你似乎有一个严重的误解。*每个翻译单元*——大约一个 C 源文件以及由它直接或间接“#include”的所有头文件——应该有其中引用的每个函数的声明。对于其他地方定义的函数,这通常是通过包含适当的头文件来完成的。正如您所介绍的,您的“main.c”没有执行此操作,但它需要执行此操作。相同的标题是否包含在其他翻译单元中是一个完全独立的问题。 (2认同)
  • @Badda,将“#include”指令添加到您的“main.c”*不应该*导致任何错误,并且*不会*使用您提供的代码(并按照我的方式布置)对我造成任何错误需要推断)。事实上,它很好地解决了所有编译器警告。如果您观察到不同的结果,那么您就遗漏了与您的问题相关的内容。 (2认同)

Joh*_*ger 5

正如您所介绍的,您main.c包含对两个没有范围内声明的函数的调用:STLINKReadSytemCalls()printf()。这与编译器发出的警告(而不是错误)相关,并且这是您提供的代码中唯一可以解释这些警告的内容。

此时我强调的是

  1. 问题就是我刚才描述的:调用这些函数时缺少作用域内的函数声明。您的“可能导致这些错误的四个问题”(实际上只提出了三个)描述了有时会出现此类问题的各种具体途径;它们本身都不是问题。

  2. 编译器发出警告,而不是错误。这意味着它接受代码,但不能确定它是否用它做了正确的事情。特别是,它依赖参数的数量和类型来猜测参数列表,并且猜测函数返回int。这并不安全,但如果你幸运的话,它可能会起作用,或者至少看起来可行。

鉴于问题是缺少函数声明,显然,解决方案是确保提供所有需要的声明,并且它们位于引用这些函数的范围内。对于在同一 C 源代码之外的其他地方定义的函数,通常的解决方案是使用#include包含所需声明的头文件或文件。假设所讨论的标头已正确编写(标准库的标头是,以及您提供的内部标头是),这就是全部内容。

您的项目的布局并不完全清楚,但看起来您可以通过放置来实现这一点

#include <stdio.h>
#include "../header/fileProcessing.h"
Run Code Online (Sandbox Code Playgroud)

在 的开头main.c,正如 @unwind 已经建议的那样。这个改变足以让我的编译器满意。

您建议这样做会导致原始代码出现其他类型的问题。如果这是真的,那么这将构成一个完全不同的问题,如果您无法弄清楚,那么您可以考虑在这里提出它。在所提出的这个问题中没有任何迹象表明存在这样的问题,并且作为一个完全独立的问题,在这里提出这个问题是不合适的。


fileProcessing.h #include顺便说一句,我补充说,我发现你的标准stdio.hstdlib.h和标头有点奇怪(但没有错)string.h,即使它不依赖于它们中的任何一个。作为样式规则,我强烈建议每个源文件(包括头文件)都应包含#include它们直接使用的功能所需的所有标头,而不是其他标头。为了支持这一点,所有标头还应该具有适当的多重包含防护,正如您提供的标头实际上所做的那样。

因此,我会fileProcessing.h像这样重写:

#ifndef FILEPROCESSING_H_
#define FILEPROCESSING_H_

int STLINKReadSytemCalls(void);

#endif /* FILEPROCESSING_H_ */
Run Code Online (Sandbox Code Playgroud)

...并让其他文件#include根据需要处理上述三个标准库头中的任何一个或全部。