为什么#include是? 不需要使用 printf() 吗?
会议记录:
> type lookma.c
int main() {
printf("%s", "no stdio.h");
}
> cl lookma.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.762 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.
lookma.c
Microsoft (R) Incremental Linker Version 8.00.50727.762
Copyright (C) Microsoft Corporation. All rights reserved.
/out:lookma.exe
lookma.obj
> lookma
no stdio.h
Session transcript:
> type lookma.c
int main() {
printf("%s", "no stdio.h");
}
> cl lookma.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.762 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.
lookma.c
Microsoft (R) Incremental Linker Version 8.00.50727.762
Copyright (C) Microsoft Corporation. All rights reserved.
/out:lookma.exe
lookma.obj
> lookma
no stdio.h
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您最初已标记此 C++,但它看起来是一个 C 程序。 如果作用域中没有原型(例如由于省略了#include),C 将自动为函数提供隐式声明。 隐式声明为:
意味着 printf 是一个返回 int 且可以接受任意数量参数的函数。 这个原型恰好适合您的需求。 你应该#include
最后,我应该补充一点,当前的 C 标准(ISO/IEC 9899:1999 或通俗地说“C99”)不允许隐式声明,并且该程序不符合该标准。 隐式声明已被删除。 我相信你的编译器不支持C99。 C++也要求正确的原型并且不做隐式声明。
You had originally tagged this C++, but it would appear to be a C program. C will automatically provide an implicit declaration for a function if there is no prototype in scope (such as due to the omission of #include <stdio.h>). The implicit declaration would be:
Meaning that printf is a function that returns an int and can take any number of arguments. This prototype happened to work for your call. You should #include <stdio.h>
Finally, I should add that the current C standard (ISO/IEC 9899:1999 or colloquially "C99") does not allow implicit declarations, and this program would not conform. Implicit declarations were removed. I believe your compiler does not support C99. C++ also requires correct prototypes and does not do implicit declarations.
在严格合规模式(这意味着“理论上”)下,当您调用一个采用可变数量参数且在作用域内没有函数原型声明的函数时,您会调用未定义的行为(这是不好的)。 这意味着编译器可以对使用
printf()
的程序执行任何操作,而无需使用#include
中的原型或等效声明。 “随心所欲”包括正确工作作为选项之一; 这似乎是您的示例选择的选项。实际上,即使没有
printf()
函数的正式声明,代码也可以在大多数实用编译器中正常工作。正如 qrdl 所指出的,该函数被发现是因为 C 编译器链接了 C 库。
请注意,Chris Young 关于 C99 和“隐式 int”的评论是准确的,但有关“变量参数函数必须在作用域内具有原型”的规则适用于 C89 和 C99。 默认情况下,大多数编译器并不在严格的 C99 兼容模式下工作,因为有太多代码无法像这样编译。
克里斯·杨评论道:
克里斯当然是正确的。 C99 标准中删除了两个“隐式声明”功能。 标准的前言将它们列出为:
int
我没有考虑(因此没有写)得足够清楚。 尽管如此,C89 和 C99 都需要一个具有可变数量参数的函数作用域原型。
举例说明:
如果没有第一行,这是一个正确的 C89 片段,其中隐式声明函数
pqr()
作为返回整数的函数(带有未指定的参数)。 如果第一行替换为extern pqr();
,那么这是一个正确的 C89 片段,其中显式声明pqr()
作为返回整数的函数 (带有未指定的参数),但返回类型是“隐式int
”。 正如所写,该函数已显式声明并具有显式int
返回类型 - 但它仍然具有未指定的参数。 我相信 C99 是有效的——尽管并不完全理想。 当然,GCC (3.4.4) 使用选项“-std=c99 -pedantic
”接受它。理想情况下,函数声明应包含完整的原型。(并且,如果pqr()
是用省略号定义的,理论上需要该原型!)In strict compliance mode (that means "in theory"), you invoke undefined behaviour (which is bad) when you call a function that takes a variable number of arguments without a prototype declaration of the function in scope. That means that the compiler is allowed to do anything it likes with a program that uses
printf()
without the prototype from#include <stdio.h>
or an equivalent declaration. "Anything it likes" includes working correctly as one of the options; that seems to be the option chosen by your example.In practice, the code will work OK with most practical compilers even without the formal declaration of the
printf()
function.As was pointed out by qrdl, the function was found because the C compiler links with the C library.
Note that Chris Young's comment about C99 and 'implicit int' is accurate, but the rule about 'variable arguments functions must have a prototype in scope' applies to both C89 and C99. Most compilers do not work in a strict C99 compatibility mode by default because there is too much code that would not compile like that.
Chris Young commented:
Chris is, of course, correct. There were two 'implicit declaration' features removed from the C99 standard. The foreword to the standard lists them as:
int
I was not thinking (and hence not writing) clearly enough. Nevertheless, both C89 and C99 require a prototype in scope for functions that take a variable number of arguments.
To illustrate:
Without the first line, this is a correct C89 fragment with an implicit declaration of the function
pqr()
as a function that returns an integer (with unspecified arguments). If the first line is replaced byextern pqr();
, then this is a correct C89 fragment with an explicit declaration ofpqr()
as a function that returns an integer (with unspecified arguments), but the return type is 'implicitint
'. As written, the function is explicitly declared and has an explicitint
return type - but it still has unspecified arguments. I believe that is valid C99 - albeit not wholly desirable. Certainly, GCC (3.4.4) accepts it with the options '-std=c99 -pedantic
". Ideally, the function declaration should include the full prototype. (And, ifpqr()
were defined with ellipsis, that prototype would be required in theory!)printf()
位于标准 C 库中,链接器始终将标准库链接到可执行文件,因此将找到任何标准函数,并且不会出现链接问题。未能包含适当的标头会导致使用未原型化的函数,这可能会导致问题,因为 C 编译器假定没有原型的函数返回
int
并采用可变数量的参数。 因此,请始终包含标题 - 这是您的安全围栏。printf()
is located in the standard C library and the linker always links the standard library to your executable, so any standard functions will be found and there will be no linking problems.Failure to include the appropriate header results in using a function that wasn't prototyped that can lead to problems, as the C compiler assumes that a function without a prototype returns
int
and takes a variable number of arguments. So always include the header - it's your safety fence.