Printf and scanf work without stdio.h, why? [duplicate]
Possible Duplicate:
Why #include <stdio.h> is not required to use printf()?
Both printf
and scanf
have been declared in stdio.h. But they work even without that, d开发者_开发知识库ropping just a warning message? What's the theory behind this?
Calling a function without declaring it will create an implicit declaration based on the parameters you give and an assumed return type of int
. This lets it get past the compilation stage, since the function could exist somewhere else that isn’t known until link time — C didn’t always have function prototypes, so this is for backwards compatibility. (In C++, it’s an error, and in C99 GCC gives a warning.)
If you look at the man page (on FreeBSD and Darwin, at least) for printf
, scanf
, puts
, etc., it says that it comes from the “Standard C Library (libc, -lc)”. GCC implicitly links with the standard C library. If you link with the -nostdlib
flag, you'll get the “undefined symbols” error that you're expecting.
(In fact, when I turn off libc
, my GNU/Linux system complains about the absence of _start
as well, and my OpenBSD system complains about _start
, __guard
, and __stack_smash_handler
.)
By default the C compiler assumes that functions that do not have a declaration return an int and does not check the parameters to the function. It it can find a declaration then the compiler will do checking of the parameters
Because in C you do not have to provide prototype of functions, there is standard conversion of passing parameters, thus if you pass parameters of same types it should work.
Back to early days of C, there where no prototypes at all, they where added later.
Note: this is different in C++, calling function without prototype on C++ would lead to compilation error.
In C, if you don't declare a function, and then you use it anyway, by default it returns type int
. (Incidentally that is also the return type of these functions.) Also, in the olden days (pre-ANSI) I believe it didn't matter whether or not you specified the names or types of arguments to functions in a prototype. So even though for your case printf()
is declared as int printf();
you can pass it arguments and it won't complain. I'm not sure that there's any guarantee in the standard that a function declared as such will have the same calling convention as int (*)(const char *, ...)
, but for most compilers I'm going to guess that the answer is yes. So it worked.
Note the rules are different for C++. If you compiled your code as C++ my guess is the compiler wouldn't accept it.
When your compiler warns you, you should figure out what that means, and fix the problem. The fact that a compiler warns you about invalid code and then goes on to compile the code means little.
As to why they work, the answer is "bad luck". It only seems to work for you, but it is not guaranteed to according to the C standard.
Th GCC compiler, which I suspect you are using, actually "knows" about some of the commonly used functions like printf, and has special code to process them. This allows it to do things like checking printf's format string, which are not required by the C or C++ standards.
精彩评论