简体   繁体   English

C函数调用:了解“隐式int”规则

[英]C function calls: Understanding the “implicit int” rule

If "a function" were compiled separately, the mismatch would not be detected, "the function" would return a double that main would treat as an int... In the light of what we have said about how declarations must match definitions this might seems surprising. 如果“函数”是分别编译的,则不会检测到不匹配,“函数”将返回一个将main视为int的双精度...根据我们所说的关于声明如何必须与定义匹配的说法,这可能似乎令人惊讶。 The reason a mismatch can happen is that if there is no function prototype, a function is implicitly declared by its first appearance in an expression, such as 可能会发生不匹配的原因是,如果没有函数原型,则该函数会通过其在表达式中的首次出现来隐式声明,例如

    sum += "the function"(line);

If a name that has not been previously declared occurs in an expression and is followed by a left parenthesis, it is declared by context to be a function name, the function is assumed to return an int, and nothing is assumed about its arguments. 如果在表达式中出现一个之前未声明的名称,并在其后加上左括号,则上下文将其声明为函数名称,假定该函数返回一个int值,并且不假设其参数成立。

I apologize beforehand for the ambiguous question, but what does this mean? 对于这个模棱两可的问题,我事先表示歉意,但这意味着什么呢?

By the way this is page 73 chapter 4.3 from Brian W. Kernighan and Dennis M. Ritchie's C Programming Language book, 2nd edition. 顺便说一下,这是Brian W. Kernighan和Dennis M. Ritchie的C编程语言第二版的第73页第4.3章。

K&R2 covers the 1989/1990 version of the language. K&R2涵盖了1989/1990版本的语言。 The current ISO C standard, published in 1999 2011, drops the "implicit int" rule, and requires a visible declaration for any function you call. 当前的ISO C标准于 1999 2011 发布,它删除了“隐式int”规则,并且要求您对任何调用的函数进行可见声明。 Compilers don't necessarily enforce this by default, but you should be able to request more stringent warnings -- and you definitely should. 编译器不一定默认会强制执行此操作,但是您应该能够请求更严格的警告-而且您绝对应该这样做。 In well-written new code, the rule is irrelevant (but it is necessary to understand it). 在编写良好的新代码中,该规则是不相关的(但必须理解它)。

An example: the standard sqrt() function is declared in <math.h> : 一个例子:标准的sqrt()函数在<math.h>声明:

double sqrt(double);

If you write a call without the required #include <math.h> : 如果您写的电话没有必需的#include <math.h>

double x = 64.0;
double y = sqrt(x);

a C90 compiler will assume that sqrt returns int -- and it will generate code to convert the result from int to double . C90编译器将假定 sqrt返回int ,并且它将生成代码以将结果从int转换为double The result will be garbage, or perhaps a crash. 结果将是垃圾,或者可能是崩溃。

(You could manually declare sqrt yourself, but that's the wrong solution.) (您可以自己手动声明sqrt ,但这是错误的解决方案。)

So don't do that. 所以不要那样做。 Always include whatever header is required for any function you call. 始终包括调用的任何函数所需的标头。 You might get away with calling an undeclared function if it does return int (and if your compiler doesn't enforce strict C99 or C11 semantics, and if a few other conditions are satisfied), but there's no good reason to do so. 如果未声明的函数确实返回int (并且编译器未强制执行严格的C99或C11语义,并且满足其他一些条件),则可能不愿调用它,但是没有充分的理由这样做。

Understanding the "implicit int" rule is still useful for understanding the behavior of old or poorly written code, but you should never depend on it in new code. 理解“隐式int”规则对于理解旧的或编写得不好的代码的行为仍然很有用,但是在任何新代码中都不要依赖它。

Function prototypes were introduced into the language late. 函数原型后来被引入该语言。

Before prototypes, the compiler would assume that every argument passed to every unknown function should be passed as an integer and would assume that the return value was also an integer. 在原型设计之前,编译器将假定传递给每个未知函数的每个参数都应作为整数传递,并假定返回值也是整数。

This worked fine for the few cases where it was correct, but meant people had to write programs in an awkward order so that functions would never rely on unknown functions that did not match this expectation. 在少数正确的情况下,这种方法很好用,但是这意味着人们必须以尴尬的顺序编写程序,以使函数永远不会依赖符合此期望的未知函数。

When prototypes were introduced into C89 (aka ANSI C or ISO C), the prototypes allow the compiler to know exactly what types of arguments are expected and what types of results will be returned. 当将原型引入C89(也称为ANSI C或ISO C)时,这些原型使编译器确切地知道需要哪种类型的参数以及将返回哪种类型的结果。

It is strongly recommended that you use function prototypes for all new code; 强烈建议您对所有新代码使用函数原型; when working on an entirely old code base, the prototypes might be harmful. 在完全旧的代码库上工作时,原型可能有害。 (Or, if the code must be compilable on a pre-ANSI C compiler, then you might wish to leave off the prototypes so it can be built on the ancient software. gcc is the only place I've seen this in a long time.) (或者,如果代码必须可以在ANSI C之前的编译器上编译,那么您可能希望放弃原型,以便可以在古老的软件上进行构建gcc是我很长时间以来唯一看到的地方。)

这只是说明,如果编译器遇到了调用未知函数的代码,则它将隐式地将其视为已看过声明为int unknown();形式的原型int unknown();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM