为什么#include <stdio.h>不需要使用 printf()? [英] Why is #include <stdio.h> not required to use printf()?

查看:47
本文介绍了为什么#include <stdio.h>不需要使用 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

推荐答案

在严格合规模式下(这意味着理论上"),当您调用一个接受可变数量的函数时,您会调用未定义的行为(这是不好的)范围内没有函数原型声明的参数.这意味着编译器可以对使用 printf() 的程序做任何它喜欢的事情,而没有来自 #include <stdio.h> 的原型或等效声明.任何喜欢的东西"包括作为选项之一正常工作;这似乎是您的示例选择的选项.

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.

实际上,即使没有正式声明 printf() 函数,代码也可以在大多数实用编译器中正常工作.

In practice, the code will work OK with most practical compilers even without the formal declaration of the printf() function.

正如qrdl所指出的,找到该函数是因为C编译器与C库链接.

As was pointed out by qrdl, the function was found because the C compiler links with the C library.

请注意,Chris Young 关于 C99 和隐式 int"的评论是准确的,但关于变量参数函数必须在范围内具有原型"的规则适用于 C89 和 C99.默认情况下,大多数编译器不会在严格的 C99 兼容模式下工作,因为有太多代码无法这样编译.

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.

克里斯·杨评论道:

为了澄清,我的评论是关于 C99 删除隐式声明.通过说隐式 int",我认为您指的是允许诸如 foo(void); 之类的声明的 C89 功能;表示 int foo(void);,C99 也删除了一些东西.

To clarify, my comment was on C99 removing implicit declarations. By saying "implicit int", I think you are referring to the C89 feature of allowing declarations such as foo(void); to mean int foo(void);, something C99 also removed.

克里斯当然是正确的.从 C99 标准中删除了两个隐式声明"功能.标准的前言将它们列为:

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
  • 移除隐式函数声明

我没有足够清楚地思考(因此没有写).尽管如此,对于采用可变数量参数的函数,C89 和 C99 都需要一个原型.

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.

举例说明:

extern int pqr();
int main(void)
{
    int i = pqr(1, 3);
    return i;
}

没有第一行,这是一个正确的 C89 片段,其中将函数 pqr() 隐式声明为返回整数(带有未指定参数)的函数.如果第一行替换为 extern pqr();,那么这是一个正确的 C89 片段,其中明确声明了 pqr() 作为返回整数的函数 (带有未指定的参数),但返回类型是隐式 int".正如所写,该函数被显式声明并具有显式 int 返回类型 - 但它仍然具有未指定的参数.我相信这是有效的 C99 - 尽管不是完全可取的.当然,GCC (3.4.4) 通过选项-std=c99 -pedantic"接受它.理想情况下,函数声明应该包括完整的原型.(并且,如果 pqr() 是用省略号定义的,理论上需要该原型!)

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 by extern pqr();, then this is a correct C89 fragment with an explicit declaration of pqr() as a function that returns an integer (with unspecified arguments), but the return type is 'implicit int'. As written, the function is explicitly declared and has an explicit int 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, if pqr() were defined with ellipsis, that prototype would be required in theory!)

这篇关于为什么#include &lt;stdio.h&gt;不需要使用 printf()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆