【问题标题】:Implicit declaration of functions regardless of header include and ifndef函数的隐式声明,与头文件 include 和 ifndef 无关
【发布时间】:2017-10-16 22:52:31
【问题描述】:

我有众所周知的错误:

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 -> add include

ma​​in.c

int main(void) {

    if (STLINKReadSytemCalls() == 1)
        printf("Error in system calls.\n");
    return 0;
}

fileProcessing.c

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

int STLINKReadSytemCalls(void) {

    // mainly system calls
}

fileProcessing.h

#ifndef FILEPROCESSING_H_
#define FILEPROCESSING_H_

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

int STLINKReadSytemCalls(void);

#endif /* FILEPROCESSING_H_ */

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

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.

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

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

【问题讨论】:

  • 在使用 Eclipse 时,每个项目花费一周左右的时间来追踪所有神秘的路径并包含错误是完全正常的。
  • @Lundin 老实说,这太神秘了,我认为 Eclipse 确实会导致我的问题。是否有任何合乎逻辑且可重现的方法来修复这些错误?
  • 注意What are the benefits of a relative path such as "../include/header.h" for a header? 通常,您最好避免在包含标题的源文件中使用.. 符号。
  • 另外,你定义的头文件不应该包含它不需要编译的头文件。标题中没有任何内容需要“强大的三重奏”中的任何类型——三个最常用的标准标题,&lt;stdio.h&gt;&lt;stdlib.h&gt;&lt;string.h&gt;——所以它们不需要包含在标题中,并且可以说不应该包含在标题中。有一个短语 IWYU — 包括您使用的内容 — 以及一个确保您遵守该短语的程序(最初由 Google 制作)。您的标头违反了 IWYU。
  • 阅读您的问题后,我意识到我的标头保护装置是另一个标头的复制/粘贴。所以预处理器不想包含新的.h。可能凌晨 4 点工作与此有关...

标签: c eclipse include-path implicit-declaration


【解决方案1】:

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

#include <stdio.h>
#include "../header/fileProcessing.h"

行,这是故意的吗?否则,我认为这就是答案。

【讨论】:

  • 那些包含已经在头文件中,两次声明它们会出错。我必须将它们移到 main 中并且标题中没有包含吗??
  • @Badda,您似乎有一个严重的误解。 每个翻译单元——大致是一个C源文件和所有直接或间接#included的头文件——应该声明其中引用的每个函数。对于在别处定义的函数,这通常通过包含适当的头文件来完成。正如您所介绍的那样,您的main.c 不会这样做,但它需要这样做。相同的标题是否包含在其他翻译单元中是一个完全不同的问题。
  • @JohnBollinger 我明白你在说什么。但包含#include "../header/fileProcessing.h" 会产生first defined heremultiple definition of 之类的错误。我认为,这意味着标头已经包含在内,并且不可能执行两次。但可能我的误解比我想象的还要多。我很乐意理解。您认为在我的问题中添加这个和相应的错误是否相关?
  • @Badda,将 #include 指令添加到您的 main.c 不应导致任何错误,并且 不会对我造成任何错误使用您提供的代码(并按照我的推断进行布局)。事实上,它很好地解决了所有编译器警告。如果您观察到不同的结果,那么您就忽略了与您的问题相关的内容。
  • “如果需要,我会添加函数的主体,但我没有看到任何线索表明函数的主体可能导致包含错误”所以你认为它可以吗?如果是这样,我将删除此问题并尝试询问或更相关和准确的问题。
【解决方案2】:

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

在此我强调一点

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

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

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

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

#include <stdio.h>
#include "../header/fileProcessing.h"

main.c 的开头,正如@unwind 已经建议的那样。这种变化足以满足我的编译器。

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


顺便说一句,我觉得你的fileProcessing.h#includes 标准的stdio.hstdlib.hstring.h 标头有点奇怪(但没有错),即使它没有对其中任何一个的依赖。作为一个样式规则,我强烈建议每个源文件,包括头文件,应该#include 他们直接使用的功能所需的所有头文件,但不要使用其他头文件。为了支持这一点,所有标头还应具有适当的多重包含保护,就像您实际提供的标头一样。

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

#ifndef FILEPROCESSING_H_
#define FILEPROCESSING_H_

int STLINKReadSytemCalls(void);

#endif /* FILEPROCESSING_H_ */

...并让其他文件根据需要处理#includeing 任何或所有上述三个标准库头文件。

【讨论】:

  • 我将发布另一个问题,感谢您帮助我专注于哪些似乎有效,哪些无效。我想我可能误判了我的错误的原因,并且这样做,通过给你们不相关的信息误导了你们所有人。我很抱歉,可能这个问题需要被标记。关于我给你的数据,我认为你的回答值得接受,因为它完美地解决了我所描述的问题。
【解决方案3】:

可能是 FILEPROCESSING_H_ 符号的重用。 .h 复制粘贴可能会发生

【讨论】:

  • 尽量使用正确的拼写、标点和语法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-28
相关资源
最近更新 更多