【问题标题】:C function calls: Understanding the "implicit int" ruleC 函数调用:理解“隐式 int”规则
【发布时间】:2012-01-03 11:06:09
【问题描述】:

如果单独编译“函数”,则不会检测到不匹配,“函数”将返回一个双精度值,main 将其视为 int ... 根据我们所说的声明必须如何匹配这似乎令人惊讶。可能发生不匹配的原因是,如果没有函数原型,则函数在表达式中首次出现时会隐式声明,例如

    sum += "the function"(line);

如果一个之前没有声明过的名字出现在一个表达式中并且后跟一个左括号,它被上下文声明为一个函数名,这个函数被假定返回一个 int,并且没有任何关于它的假定论据。

我事先为这个模棱两可的问题道歉,但这意味着什么?

顺便说一下,这是 Brian W. Kernighan 和 Dennis M. Ritchie 的 C 编程语言书第 2 版的第 73 页第 4.3 章。

【问题讨论】:

  • 这是 K&R 中的哪个页面?但我认为你要问的问题是关于你声明函数/类型的默认整数,它们默认为int。我认为此线程与您的问题重复:stackoverflow.com/questions/5885156/…

标签: c function


【解决方案1】:

K&R2 涵盖了该语言的 1989/1990 版本。当前的 ISO C 标准(于 1999 2011 年发布)放弃了“隐式 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 语义,并且如果满足其他一些条件),您可能会避免调用未声明的函数,但没有充分的理由这样做。

理解“隐式 int”规则对于理解旧代码或写得不好的代码的行为仍然很有用,但你永远不应该在新代码中依赖它。

【讨论】:

    【解决方案2】:

    函数原型被引入语言较晚。

    在原型之前,编译器会假定传递给每个未知函数的每个参数都应作为整数传递,并假定返回值也是整数。

    这在少数正确的情况下工作得很好,但意味着人们必须以尴尬的顺序编写程序,以便函数永远不会依赖符合此预期的未知函数。

    当原型被引入 C89(又名 ANSI C 或 ISO C)时,原型允许编译器准确地知道预期的参数类型以及将返回的结果类型。

    强烈建议您对所有新代码使用函数原型;在完全旧的代码库上工作时,原型可能是有害的。 (或者,如果代码必须在 ANSI C 之前的编译器上编译,那么您可能希望放弃原型,以便可以在古老的软件上构建它。gcc 是我在很长一段时间。)

    【讨论】:

      【解决方案3】:

      这只是说明,如果编译器遇到调用未知函数的代码,那么它会隐式处理它,就好像它已经看到了 int unknown(); 形式的声明原型

      【讨论】:

      • @TJD:这有什么意义,什么时候可以遇到?你能举个例子吗?
      • 文本内容为“......并且没有任何关于它的论据的假设。”,但(void) 的意思是“不接受任何论据”。这与() 不同。
      • 是的,假设你的文件 1 包含一个调用,例如 x = foo();,但是你没有包含声明 foo 类型格式的头文件,而 foo 是在文件中实现的2. 编译器在生成文件1的汇编代码时,必须假设如何生成foo的调用代码和处理返回参数。它选择的假设是 1)对输入 args 不做任何事情,2)返回类型是 int
      • 另外,大多数编译器在这种情况下会生成警告,让您知道它正在做一些可能无意的猜测
      • 不,它不会选择对参数不做任何事情。它将它们传递给函数。
      猜你喜欢
      • 2019-10-05
      • 1970-01-01
      • 1970-01-01
      • 2012-04-22
      • 2018-03-06
      • 2015-05-09
      • 1970-01-01
      • 2019-04-05
      相关资源
      最近更新 更多