C中的隐式函数声明

Baz*_*oka 43 c

术语"函数的隐式声明"是什么意思.调用标准库函数而不包括相应的头文件会产生警告,如果的话

int main(){
  printf("How is this not an error?");
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

如果不声明它是错误的话,不应该使用函数吗?请详细解释.我搜索了这个网站,发现了类似的问题,但找不到明确的答案.大多数答案说了一些关于包含头文件以摆脱警告的事情.但我想知道这不是一个错误.

ugo*_*ren 74

它应该被认为是一个错误.但C是一种古老的语言,所以它只是一个警告.
-Werror(gcc)编译修复了这个问题.

当C没有找到声明时,它会假定这个隐式声明:int f();这意味着函数可以接收你给它的任何东西,并返回一个整数.如果这恰好足够接近(如果是printf这样),那么事情就可以发挥作用.在某些情况下(例如函数实际返回一个指针,指针大于整数),它可能会导致真正的麻烦.

请注意,这是在较新的C标准(C99,C11)中修复的.在这些标准中,这是一个错误.但是,gcc默认情况下不实现这些标准,因此您仍然会收到警告.

  • 你的答案是正确的,并准确地说出了K&R的说法.谢谢你的简明解释. (3认同)
  • 请注意,即使在允许隐式声明的日子里,它们仍然会为可变参数函数(如`printf`)生成UB. (2认同)
  • @R ..,原则上你是对的.在实践中,大多数实现处理一个可变参数函数,给出了n个参数,就像一个得到n个参数的普通函数一样,所以事情有效. (2认同)
  • 这个答案在 24 年前是正确的。今天是错误的。当前的 C 标准 (C11) 和广泛实施的先前标准 (C99) 都明确禁止调用未声明的函数。 (2认同)
  • 并且相同的大小是不够的 - 在大多数平台中浮点数和整数的大小相同,但返回的方式不同 (2认同)

oua*_*uah 19

隐式声明在C中无效.

C99删除了此功能(存在于C89中).

gcc选择仅默认发出警告,-std=c99但编译器有权拒绝翻译此类程序.

  • 与此相关的是,“-pedantic-errors”将使 GCC(或 CLang,就此而言)按照此处的标准运行,并拒绝编译(读取:发出错误并中止)。 (2认同)

Ant*_*nio 7

要完成图片,因为-Werror强权认为过于“侵入”,
对海湾合作委员会(和LLVM)更精确的解决方案是改造只是在一个错误此警告,使用选项:

-Werror=implicit-function-declaration
Run Code Online (Sandbox Code Playgroud)

请参阅使一个 gcc 警告成为错误?

关于一般用途-Werror:当然,建议使用无警告代码,但在开发的某些阶段,它可能会减慢原型设计的速度。


Gre*_*eys 5

C是一种非常低级的语言,因此它允许您创建几乎任何您可以想到的合法对象(.o)文件.您应该将C视为基本装扮的汇编语言.

特别是,C不需要在使用之前声明函数.如果在不声明函数的情况下调用函数,则函数的使用将成为它(隐式)声明.在我刚刚运行的简单测试中,这只是内置库函数(如printf)(至少在GCC中)的警告,但对于随机函数,它将编译得很好.

当然,当你尝试链接时,它找不到foo,那么你会收到一个错误.

对于像printf这样的库函数,一些编译器包含内置的声明,因此它们可以进行一些基本的类型检查,所以当隐式声明(来自使用)与内置声明不匹配时,你将会得到警告.

  • "特别是,C在使用之前不需要声明函数." - 确实如此.C89(允许这个)不是现行标准.C11是,C11及其过于流行的前身C99都不允许调用隐式声明的函数. (2认同)