在严格合规模式下(这意味着“理论上”),当您调用一个函数时调用未定义的行为(这很糟糕),该函数在范围内没有函数的原型声明,而该函数采用可变数量的参数。这意味着编译器可以对printf()
没有原型 from#include <stdio.h>
或等效声明的程序做任何它喜欢的事情。“任何喜欢的东西”包括作为选项之一正常工作;这似乎是您的示例选择的选项。
在实践中,即使没有函数的正式声明,代码也可以在大多数实用编译器中printf()
正常工作。
正如 qrdl 所指出的,找到该函数是因为 C 编译器与 C 库链接。
请注意,Chris Young 关于 C99 和“隐式 int”的评论是准确的,但关于“变量参数函数必须在范围内具有原型”的规则适用于 C89 和 C99。大多数编译器在默认情况下不能在严格的 C99 兼容模式下工作,因为有太多的代码不会像那样编译。
克里斯·杨评论道:
为了澄清,我的评论是关于 C99 删除隐式声明。通过说“隐式 int”,我认为您指的是允许诸如 foo(void); 之类的声明的 C89 功能;表示 int foo(void);,C99 也删除了一些东西。
克里斯当然是正确的。从 C99 标准中删除了两个“隐式声明”功能。该标准的前言将它们列为:
我没有足够清楚地思考(因此没有写作)。尽管如此,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()
用省略号定义,理论上需要该原型!)