如果"一个功能"单独编译,不会检测到不匹配,"功能"将返回一个主要将其视为int的双重...根据我们所说的关于声明必须如何匹配定义的内容,这似乎令人惊讶。可能发生不匹配的原因是,如果没有函数原型,则函数在表达式中首次出现时会隐式声明,例如
sum += "the function"(line);
如果先前未声明的名称出现在表达式中并且后面跟着左括号,则上下文将其声明为函数名称,假定该函数返回一个int,并且没有任何关于它的假设参数。
我事先为这个含糊不清的问题道歉,但这是什么意思?
顺便说一下,这是Brian W. Kernighan和Dennis M. Ritchie的C编程语言书第2版第73页第4.3章。
答案 0 :(得分:10)
K& R2涵盖1989/1990版本的语言。在 1999 2011中发布的当前ISO C标准删除了“隐式int”规则,并且要求对您调用的任何函数进行可见声明。编译器默认情况下不一定强制执行此操作,但您应该能够请求更严格的警告 - 而且您肯定应该这样做。在编写良好的新代码中,规则是无关紧要的(但有必要理解它)。
示例:标准sqrt()
函数在<math.h>
中声明:
double sqrt(double);
如果您在没有所需的#include <math.h>
:
double x = 64.0;
double y = sqrt(x);
C90编译器将假设 sqrt
返回int
- 它将生成代码以将结果从int
转换为double
。结果将是垃圾,或者可能是崩溃。
(你可以自己手动声明sqrt
,但这是错误的解决方案。)
所以不要这样做。始终包括您呼叫的任何功能所需的标头。如果它返回int
(并且如果你的编译器没有强制执行严格的C99或C11语义,并且满足一些其他条件),你可能会调用未声明的函数,但是没有充分的理由去做如此。
理解“隐式整数”规则对于理解旧代码或编写不良代码的行为仍然有用,但是你不应该在新代码中依赖它。
答案 1 :(得分:7)
函数原型最近被引入语言。
在原型之前,编译器会假设传递给每个未知函数的每个参数都应该作为整数传递,并假设返回值也是一个整数。
这适用于少数几个正确的情况,但意味着人们必须以尴尬的顺序编写程序,以便函数永远不会依赖于不符合此期望的未知函数。 / p>
当原型被引入C89(又名ANSI C或ISO C)时,原型允许编译器确切地知道预期的参数类型以及将返回的结果类型。
强烈建议您为所有新代码使用函数原型;在处理一个完全古老的代码库时,原型可能是有害的。 (或者,如果代码必须在ANSI C之前的编译器上编译,那么您可能希望不使用原型,以便可以在古老的软件上构建。gcc
是我见过的唯一的地方很长一段时间。)
答案 2 :(得分:0)
它只是声明如果编译器遇到调用未知函数的代码,那么它会隐式地将其视为已经看到了int unknown();