会议记录:

>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> 或同等声明。“随心所欲”包括正确工作作为选项之一;这似乎是您的示例选择的选项。

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

正如 qrdl 所指出的,该函数被发现是因为 C 编译器链接了 C 库。

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

克里斯·杨评论道:

为了澄清,我的评论是关于 C99 删除隐式声明。通过说“隐式 int”,我认为您指的是允许诸如 foo(void); 之类的声明的 C89 功能。表示 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() 作为返回整数(带有未指定参数)的函数,但返回类型是“隐式” int'。正如所写,该函数是显式声明的并且具有显式 int 返回类型 - 但它仍然有未指定的参数。我相信 C99 是有效的——尽管并不完全理想。当然,GCC (3.4.4) 接受它的选项 '-std=c99 -pedantic”。理想情况下,函数声明应包含完整的原型。(而如果 pqr() 用省略号定义,需要原型 理论上!)

其他提示

您最初标记这个C ++,但它似乎是一个C程序。如果在范围没有原型(例如由于的#include遗漏中)C会自动为函数提供一个隐式声明。隐式声明将是:

int printf();

含义即是printf的返回int,并且可以采用任意数量的参数的函数。这个原型发生在你的电话工作。你应该#包括

最后,我要补充的是,当前的C标准(ISO / IEC 9899:1999或通俗 “C99”)做的允许隐式声明,并且该方案不符合。隐声明被拆除。我相信你的编译器不支持C99。 C ++还需要正确的原型,并没有做隐含的声明。

printf()位于标准C库和连接器标准库始终链接到您的可执行文件,因此任何标准功能将被发现,将没有连接的问题。

没有包括在使用未原型函数相应的头的结果,可导致问题,因为C编译器假定功能,而不原型返回int并采取可变数目的参数。所以总是包括头 - 这是您的安全围栏

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top