C中的隐式函数声明
什么是术语“隐式函数声明”。 调用标准库函数时,如果不包含相应的头文件,会产生警告
int main(){ printf("How is this not an error ?"); return 0; }
不应该使用一个函数没有声明它是一个错误? 请详细解释。 我search这个网站,发现类似的问题,但无法find一个明确的答案。 大多数答案都提到了包含头文件以摆脱警告的一些信息。 但是我想知道这不是一个错误。
这应该被认为是一个错误。 但是C是一种古老的语言,所以这只是一个警告。
用-Werror
(gcc)编译解决了这个问题。
当C没有find一个声明时,它假定这个隐式声明: int f();
,这意味着该函数可以接收你给它的任何东西,并返回一个整数。 如果这种情况恰好足够接近(在printf
情况下),那么事情就会起作用。 在某些情况下(例如函数实际上返回一个指针,指针比int大),这可能会导致真正的麻烦。
请注意,这在更新的C标准(C99,C11)中得到了修复。 在这些标准中,这是一个错误。 但是, gcc
并没有默认实现这些标准,所以你仍然得到警告。
隐式声明在C中是无效的
C99删除了这个function(在C89中出现)。
gcc
select默认使用-std=c99
发出警告,但是编译器有权拒绝翻译这样的程序。
C是一种非常低级的语言,所以它允许你创build几乎任何可以想象的合法对象(.o)文件。 你应该把C看作基本打扮的汇编语言。
特别是C在使用之前不需要声明函数。 如果你调用一个没有声明的函数,函数的使用就变成了(隐式的)声明。 在一个简单的testing中,我只是跑了,这只是一个内置库函数(如printf(至less在GCC))的情况下的警告,但对于随机函数,它会编译得很好。
当然,当你尝试链接,并找不到富,那么你会得到一个错误。
在像printf这样的库函数的情况下,一些编译器包含内置的声明,所以他们可以做一些基本的types检查,所以当隐式声明(来自使用)与内置声明不匹配时,得到一个警告。
由于历史原因回到C的第一个版本,函数被假定为具有int function(int arg1, int arg2, int arg3, etc)
的隐式定义int function(int arg1, int arg2, int arg3, etc)
。
编辑:不,我错了int
的参数。 相反,它会传递任何types的参数。 所以它可能是一个int
或一个double
或一个char*
。 如果没有原型,编译器会传递任何大小的参数,被调用的函数最好使用正确的参数types来接收它。
有关更多详情,请查阅K&R C
为了完成这个画面,因为 – -Werror
可能被认为是太“侵入”了,
对于gcc(和llvm)来说,一个更精确的解决scheme就是将这个警告转换成一个错误,使用下面的选项:
-Werror=implicit-function-declaration
请参阅使一个海湾合作委员会警告错误?
关于一般的使用 – -Werror
:当然,有一些无需警告的代码是值得推荐的,但在某些发展阶段可能会减慢原型devise。
隐式声明的函数是既没有原型也没有定义,但在代码中被调用的地方。 因此,编译器不能validation这是函数的预期用法(参数的数量和types是否匹配)。 在编译之后,在链接时parsing对引用的引用(与所有其他全局符号一样),所以在技术上,跳过原型不是问题。
假定程序员知道他在做什么,这是提供原型的正式合同被省略的前提。
如果使用错误types或数量的参数调用函数,可能会发生恶意错误。 这个最可能的performance是堆栈的腐败。
现在这个function可能看起来不太古怪,但在过去,这是一种减less头文件数量的方法,因此编译速度更快。