可能是重复问题:
为什么使用printf()不需要#include <stdio.h>?
无论如何,printf
和scanf
都在stdio.h中声明。但即使没有它们,它们仍然可以工作,只会提示警告信息?这背后的理论是什么?
可能是重复问题:
为什么使用printf()不需要#include <stdio.h>?
无论如何,printf
和scanf
都在stdio.h中声明。但即使没有它们,它们仍然可以工作,只会提示警告信息?这背后的理论是什么?
int
。这使得它可以通过编译阶段,因为该函数可能存在于其他位置,直到链接时间才知道 - C并不总是有函数原型,因此这是为了向后兼容性。(在C ++中,这是一个错误,在C99 GCC中会给出警告。)printf
,scanf
,puts
等的手册页(至少在FreeBSD和Darwin上),它说它来自“标准C库(libc,-lc)”。GCC隐式地链接标准C库。如果您使用-nostdlib
标志进行链接,则会得到您预期的“未定义符号”错误。libc
时,我的GNU/Linux系统还抱怨缺少_start
,而我的OpenBSD系统则抱怨_start
、__guard
和__stack_smash_handler
的缺失。)默认情况下,C编译器假设没有声明的函数返回一个int类型,并且不会检查函数的参数。如果能够找到声明,则编译器将进行参数检查。
当编译器发出警告时,你应该弄清楚这意味着什么,并解决问题。编译器警告你代码无效,然后继续编译代码的事实意义不大。
至于为什么它们能工作,答案是“运气不好”。它似乎只对你有效,但根据C标准并不保证。
printf
和 scanf
)- 这是未定义的行为。 - cafint
。(顺便说一句,这些函数的返回类型也是int
。)此外,在旧时代(ANSI之前),我相信无论您是否在原型中指定了参数的名称或类型,都不会影响函数的参数。因此,即使对于您的情况,printf()
被声明为int printf();
,您仍然可以传递参数给它而不会出错。我不确定标准中是否有任何保证,声明为这样的函数将具有与int (*)(const char *, ...)
相同的调用约定,但对于大多数编译器,我猜答案是肯定的。所以它能够工作。我猜测您正在使用的是GCC编译器,它实际上“知道”一些常用函数,比如printf,并有特殊代码来处理它们。这使得它能够执行像检查printf格式字符串等C或C++标准不要求的操作。