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

查看:64
本文介绍了为什么#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和'implicit 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.

克里斯·杨(Chris Young)评论:

Chris Young commented:

为了澄清,我的评论是关于C99删除隐式声明的.通过说"implicit 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()作为返回整数的函数((带有未指定的参数),但是返回类型为'implicit int '.按照书面说明,该函数已显式声明,并且具有显式的 int 返回类型-但它仍具有未指定的参数.我相信这是有效的C99-尽管并非完全可取.当然,GCC(3.4.4)可以通过选项' -std = c99 -pedantic 接受它.理想情况下,函数声明应包含完整的原型.(并且,如果 pqr()用省略号定义,理论上需要原型[em> !)

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天全站免登陆