代码之家  ›  专栏  ›  技术社区  ›  Constantin

为什么不需要include<stdio.h>来使用printf()?

  •  28
  • Constantin  · 技术社区  · 17 年前

    会议记录:

    >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
    
    3 回复  |  直到 17 年前
        1
  •  31
  •   vaxquis user2577497    10 年前

    在严格的遵从模式下(这在理论上意味着“在理论上”),当您调用一个函数时,如果该函数接受的参数数目可变,并且在范围内没有函数的原型声明,则会调用未定义的行为(这很糟糕)。这意味着编译器可以对使用 printf() 没有原型 #include <stdio.h> 或同等声明。”它喜欢的任何东西“都包括作为选项之一正确工作;这似乎是您的示例选择的选项。

    在实践中,即使没有 Primff() 功能。

    正如qrdl所指出的,找到这个函数是因为C编译器链接到C库。

    注意,Chris Young关于c99和“implicit int”的评论是准确的,但是关于“variable arguments functions must have a prototype in scope”的规则适用于c89和c99。默认情况下,大多数编译器不在严格的C99兼容模式下工作,因为有太多的代码无法这样编译。

    克里斯·杨评论道:

    为了澄清,我的评论是关于c99删除隐式声明。通过说“隐式int”,我认为您指的是允许声明的C89特性,比如foo(void);意思是int foo(void);一些c99也被删除了。

    克里斯当然是对的。从C99标准中删除了两个“隐式声明”功能。标准前言将其列为:

    • 删除隐式 int
    • 删除隐式函数声明

    我想得不够清楚(因此也写不清楚)。然而,C89和C99都需要一个范围内的原型,用于接受可变数量参数的函数。

    举例说明:

    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() 是用省略号定义的,需要该原型 理论上 !)

        2
  •  37
  •   Chris Young    17 年前

    您最初标记了这个C++,但是它看起来是一个C程序。如果作用域中没有原型(例如由于省略了include<stdio.h>),C将自动为函数提供隐式声明。隐式声明将是:

    int printf();
    

    这意味着printf是一个返回int的函数,可以接受任意数量的参数。这个原型正好适合你的电话。您应该包括<stdio.h>

    最后,我应该补充一下,当前的C标准(ISO/IEC 9899:1999或通俗地说“C99”)是这样的 允许隐式声明,此程序将不符合。隐式声明已删除。我相信您的编译器不支持C99。C++还需要正确的原型,不做隐式声明。

        3
  •  9
  •   qrdl    17 年前

    printf() 位于标准C库中,链接器始终将标准库链接到可执行文件,因此将找到任何标准函数,并且不会出现链接问题。

    如果不包含适当的头,则会导致使用未原型化的函数,从而导致问题,因为C编译器假定该函数没有原型返回 int 并接受可变数量的参数。所以一定要包括头部-这是你的安全围栏。