Hi Group,
I am a little hesitant to ask this, after having read the "your
question is less lively than a dead parrot answer!", but here goes.
(Read thru the Faq, may have missed this, in which case would be happy
to be steered correctly.)
I can't remember whether this is in the FAQ or not, and can't
particularly be bothered to look right now, so we'll discuss it.
Could someone give me an understanding why
.........
printf("foobar")
.......
without the directive #include<stdio> still prints, but does so (in
Xcode 2.2) with a warning. Clearly, I am trying to gain an overview of
C, and am obviously missing something about compiling/linking etc.
I have absolutely no idea what "Xcode 2.2" is, but don't bother to
explain, it is not particularly relevant to your question.
Let's stroll down memory lane and talk about function declarations and
prototypes in C over the years as the language evolved.
The first C "standard" was the first edition of "The C Programming
Language" by Kernighan & Ritchie, published in 1979. There was no
such thing as a function prototype, and no need of declarations for
most functions.
If the compiler saw a function call expression that it had not seen a
declaration for, it assumed that it was a function returning an int
and it accepted whatever arguments you called it with.
If a function returned something other than an int it required a
declaration, such as:
double sqrt();
The printf() function does indeed return an int, and it accepts one or
more arguments, the first one must be a pointer to char. In your
code, your call to printf() has a single argument, a string literal,
which is converted to pointer to char and that is what is passed to
printf().
So in a "K&R" version of C, your code is perfectly correct.
The first true C standard, ANSI/ISO of 1989 and 1990, changed things.
First of all, prototypes were added to the language. A function
declaration could provide the compiler with information about the
function's arguments, although it was not required to do so except in
certain special cases.
The special cases are "variadic" functions, that is those that take a
variable number of arguments. And, of course, printf() is one of
those functions. Its prototype is:
int printf(const char *fmt_string, ...);
The "..." after the comma indicates one or more additional arguments
of unspecified types.
Still, if a function had a fixed argument list, and returned an int,
you did not need to provide either a prototype or declaration for it.
There was a major update to the C standard in 1999, although not too
many compilers support it at this time. This version of the standard
banned the "implicit int" feature of the language, and required that
all functions have at least a declaration in scope that specified
their return type.
All versions of the ANSI/ISO C standard, from 1989 on, have required
that you have a proper prototype in scope when you call a variadic
function. Calling such a function without a prototype in scope causes
undefined behavior, which means that the language standard no longer
specifies what should happen. There is no requirement that a compiler
recognize and diagnose undefined behavior. There is no requirement
that the program fail. It might well do what you expected it to do
when you caused the undefined behavior.
So we have two possibilities here. Either you are using a
pre-standard compiler, or the undefined behavior just happens to
"work" the same way the program would work if you had included the
proper header.
I know of several implementations where a call to printf() without a
prototype in scope will cause programs to hang or crash. Undefined
behavior is like that.