General question

D

drM

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.)

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.

Thanks
 
J

Jack Klein

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.
 
I

Ian Collins

drM said:
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.)

Could someone give me an understanding why


..........

printf("foobar")


........

without the directive #include<stdio>

That's <stdio.h>

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.
The compiler will warn you that the function is implicitly declared
(there isn't a prototype), but the linker is still able to resolve the
symbol.

This can have disastrous results if you pass the wrong parameters to an
unknown function....
 
M

Martin Ambuhl

drM said:
Could someone give me an understanding why

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.

The warning is because using printf() without a prototype makes it have
an implicit declaration (before C99) with a fixed number of arguments
and a return type of int. Clearly, printf takes a variable number of
arguments and its declaration, provided by a prototype in <dtdio.h>,
must end in an ellipsis (, ...).

Many compilers "know" about printf. This allows them, for example, to
issue diagnostics for incorrect specifiers. But knowing about printf
also means that they know what the prototype looks like, and so they can
produce what one might call working executables. Other implementations
may just pass any arguments with the default conversions and rely on the
called function to sort them out.

It is a bad practice to rely on any such behavior, and with a C99
compiler not an allowed one. I think you knew that already, though.
Even though I have given an explanation of why your code might be
working, the real position to taken in comp.lang.c is that there is *no*
explanation of why incorrent code "works" other than plain (bad) luck.
 
J

Jordan Abel

The warning is because using printf() without a prototype makes it have
an implicit declaration (before C99) with a fixed number of arguments

Not quite. It's actually a declaration with no particular number of
arguments, such that it can be called with any arguments with no
required diagnostic.
 
F

Flash Gordon

Jordan said:
Not quite. It's actually a declaration with no particular number of
arguments, such that it can be called with any arguments with no
required diagnostic.

As well as not requiring a diagnostic, it is also not required to work
if it is a varidac function or if the number and type (after promotion)
of parameters is not correct.
 
E

Eric Sosman

Jordan Abel wrote On 03/27/06 10:45,:
Not quite. It's actually a declaration with no particular number of
arguments, such that it can be called with any arguments with no
required diagnostic.

Martin's right: The implicit declaration is for a
function taking a fixed number of arguments. The value
of the fixed number is unknown, but the number is fixed
nonetheless. That is, the implicit declaration is never
of a variadic function, hence an implicit declaration of
printf() is always wrong.

Jordan's right: No diagnostic is required if a call
provides the wrong number of arguments, or even if different
calls provided different numbers of arguments. Nor is a
diagnostic required if the arguments' promoted types fail
to match those of the function's formal parameters.

"And I am right, and you are right, and everything
is quite correct." -- Pish-Tush
 
M

Martin Ambuhl

Jordan said:
Not quite. It's actually a declaration with no particular number of
arguments, such that it can be called with any arguments with no
required diagnostic.

I did not claim it was a declaration with a particular number of
arguments. I claimed that it was a declaration with a fixed number of
arguments. Just as it can be called "with no required diagnostics", it
call be called with no reason to expect it to work.
 
J

Jordan Abel

Jordan's right: No diagnostic is required if a call
provides the wrong number of arguments, or even if different
calls provided different numbers of arguments. Nor is a
diagnostic required if the arguments' promoted types fail
to match those of the function's formal parameters.

And of course, in the older [K&R] dialects of C that this convention
comes from, there were several functions that were actually well-defined
on different numbers or types of parameters. printf is the obvious one
one. also open() and, i believe, signal handlers.
 
J

Jordan Abel

As well as not requiring a diagnostic, it is also not required to work
if it is a varidac function or if the number and type (after promotion)
of parameters is not correct.

I didn't say that it was _right_, just that it didn't require
a diagnostic. Which is in some ways worse.
 
J

Jordan Abel

I did not claim it was a declaration with a particular number of
arguments. I claimed that it was a declaration with a fixed number of
arguments.

But it's not. It is a declaration with empty parentheses, and you can
subsequently call the function with a different number of arguments,
almost certainly invoking undefined behavior.
 
V

void * clvrmnky()

Jack said:
comp.lang.c: [...]
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.
Xcode is the Mac OS X C/C++/Objective-C/etc./etc. development system.
Essentially a hacked GCC.
 
D

Dave Thompson

comp.lang.c:
(calling printf without inlcuding stdio.h)
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.
After promotion(s) of small integers to int and float to double.
If a function returned something other than an int it required a
declaration, such as: <snip>
So in a "K&R" version of C, your code is perfectly correct.
Right.

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 <snip>
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.
A prototype is also required when calling a function defined with one
containing narrow type parameters. If defined K&R1-style parameter
passing uses the promoted type(s) and it may be called with either a
K&R1 declaration or none, or a prototype using promoted types.
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.
Although quite a few C89 compilers implement(ed) at least an optional
warning for implicit function declaration. (I don't even say as an
extension, since warning for anything was already permitted.)

<snip rest>
- David.Thompson1 at worldnet.att.net
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,177
Messages
2,570,953
Members
47,507
Latest member
codeguru31

Latest Threads

Top