为什么 "implicit declaration of function" 只是一个警告?

Why is "implicit declaration of function" just a warning?

这不是关于如何解决 C 程序中出现的 "implicit declaration of function" 警告的问题,已经 answered 多次了。

我知道这是一个编译器警告,我想知道为什么这是一个警告而不是错误?如果编译器看不到该函数,那么在运行时调用该函数时会发生什么?链接器是否最终解决了这个问题?或者我们是否假设调用产生此类警告的函数的行为是未知的?

该标准对有关诊断的实现提出了非常少的要求:

5.1.1.3 Diagnostics

1     A conforming implementation shall produce at least one diagnostic message (identified in an implementation-defined manner) if a preprocessing translation unit or translation unit contains a violation of any syntax rule or constraint, even if the behavior is also explicitly specified as undefined or implementation-defined. Diagnostic messages need not be produced in other circumstances.9)
9) The intent is that an implementation should identify the nature of, and where possible localize, each violation. Of course, an implementation is free to produce any number of diagnostics as long as a valid program is still correctly translated. It may also successfully translate an invalid program.

因为主流编译器(包括您正在使用的编译器)发扬的有害传统。值得庆幸的是,他们通常可以选择使其成为错误,例如 -Werror=implicit-function-declaration 用于 gcc 和兼容的编译器。

why is this a warning rather than an error?

因为有很多遗留代码,所以是这样写的。编译器错误会破坏它。

If the compiler cannot see the function, what happens when the function is called at runtime? Does the linker ultimately resolve this issue?

我们来看例子:

int main()
{
    foo();
    return 0;
}

运行时,编译器会生成自己的函数签名,如 int foo(...) 并将使用它。顺便说一句,它可能会导致非常奇怪的错误。所以目标文件会包含这个函数的调用就可以了。当你尝试 link 时,你会得到一个错误:未定义对 `foo' 的引用。但是,如果您有另一个具有 foo 定义的模块,linker 将通过名称和 link 找到它。

Or are we to assume that the behaviour of calling a function that produced such warning is unknown?

正如我所说,它可能会导致一些奇怪的错误。想象一下,您有像 int i = foo() 这样的代码,而 foo 没有签名。在另一个模块中,您有以下内容:int * foo(){...}。在 64 位模式下构建应用程序时,您将仅向 i 放置 64 位指针的 32 位。所以你可能会说事实上你的程序的行为可能是未知的。