会议记录:
>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
Chris Young.. 37
您最初标记了此C++,但它似乎是一个C程序.如果范围中没有原型(例如由于省略#include
int printf();
这意味着printf是一个返回int的函数,可以接受任意数量的参数.这个原型恰好适合您的通话.你应该#include
最后,我要补充的是,当前的C标准(ISO/IEC 9899:1999或俗称"C99")都不会允许隐式声明,并将该软件将不符合.删除了隐式声明.我相信你的编译器不支持C99.C++还需要正确的原型,不进行隐式声明.
您最初标记了此C++,但它似乎是一个C程序.如果范围中没有原型(例如由于省略#include
int printf();
这意味着printf是一个返回int的函数,可以接受任意数量的参数.这个原型恰好适合您的通话.你应该#include
最后,我要补充的是,当前的C标准(ISO/IEC 9899:1999或俗称"C99")都不会允许隐式声明,并将该软件将不符合.删除了隐式声明.我相信你的编译器不支持C99.C++还需要正确的原型,不进行隐式声明.
在严格的合规模式(意思是"在理论上")中,当您调用一个函数时调用未定义的行为(这是不好的),该函数接受可变数量的参数而没有函数的原型声明.这意味着允许编译器使用printf()
没有原型#include
或等效声明的程序执行任何它喜欢的操作."任何它喜欢的东西"包括正确地作为选项之一; 这似乎是你的例子选择的选项.
实际上,即使没有printf()
函数的正式声明,代码也可以在大多数实用编译器中正常工作.
正如qrdl所指出的,找到了该函数,因为C编译器与C库链接.
请注意,Chris Young关于C99和'implicit int'的评论是准确的,但关于'变量参数函数必须在范围内具有原型'的规则适用于C89和C99.默认情况下,大多数编译器不能在严格的C99兼容模式下工作,因为有太多的代码无法像这样编译.
Chris Young评论道:
为了澄清,我的评论是关于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()
为返回整数的函数(带有未指定的参数),但返回类型为"隐式int
".如上所述,该函数是显式声明的,并且具有显式的int
返回类型 - 但它仍然具有未指定的参数.我相信这是有效的C99 - 尽管不是完全可取的.当然,GCC(3.4.4)接受选项' -std=c99 -pedantic
".理想情况下,函数声明应该包括完整的原型.(如果pqr()
用省略号定义,原型在理论上是必需的!)
printf()
位于标准C库中,链接器始终将标准库链接到您的可执行文件,因此将找到任何标准函数,并且不会出现链接问题.
未能包含适当的头导致使用非原型的函数可能导致问题,因为C编译器假定没有原型的函数返回int
并且接受可变数量的参数.所以总是包括标题 - 这是你的安全围栏.