is this declaration correct

R

Raj Pashwar

Rather than
include <stdio.h> can I use int printf(const char *,...) correct at all
places if I only use printf in my program..

Cheers
 
K

Keith Thompson

Raj Pashwar said:
Rather than
include <stdio.h> can I use int printf(const char *,...) correct at all
places if I only use printf in my program..

You *can*, but there's no good reason to do so.

It's permitted by 7.1.4p2 (7.1.7 in C89/C90):

Provided that a library function can be declared without
reference to any type defined in a header, it is also permissible
to declare the function and use it without including its
associated header.

The <stdio.h> header exists precisely so you don't have write your own
declarations for standard functions. Using it guarantees (assuming your
implementation isn't broken) that the declarations will be correct.
If you write your own declarations, there's always a risk that you'll
get something wrong.

And in fact, you have. The declaration you show:

int printf(const char *,...);

is correct for C89/C90, but starting with C99 the declaration changed
to:

int printf(const char * restrict, ...);

(Omitting the "restrict" *probably* won't cause any problems, but it
could inhibit some optimizations.)

And even that works only because printf doesn't happen to depend on any
other declarations in <stdio.h>. You can't declare fprintf this way, for
example, because it depends on the definition of FILE -- and its
definition can vary substantially from one implementation to another.

Just write "#include <stdio.h>" and be done with it.
 
E

Eric Sosman

Rather than
include <stdio.h> can I use int printf(const char *,...) correct at all
places if I only use printf in my program..

You could, but it would be both silly and dangerous. "Silly"
because the actual declaration in some implementation's <stdio.h>
might be something like

int printf(const char restrict *, ...)
__attribute__((format(printf,1,2)));

.... where the extra stuff enables implementation-specific extra
magic, and by using your own free-hand declaration you might lose
whatever benefits the magic offers. "Dangerous" because strange
things may happen if you get the declaration wrong -- and note that
typing ten more characters than `#include <stdio.h>' gives you ten
additional chances to blunder.

The Fourth Commandment reads

If thy header files fail to declare the return types of
thy library functions, thou shalt declare them thyself
with the most meticulous care, lest grievous harm befall
thy program.

.... and the scholarly annotations thereto say,

The prophet Ansi, in her wisdom, hath added that thou
shouldst also scourge thy Suppliers, and demand on pain
of excommunication that they produce header files that
declare their library functions. For truly, only they
know the precise form of the incantation appropriate to
invoking their magic in the optimal way.

The prophet hath also commented that it is unwise, and
leads one into the pits of damnation and subtle bugs, to
attempt to declare such functions thyself when thy header
files do the job right.

But hey, go ahead, do as you please. As the Sowerberrys so
succinctly put it: "That's - Your - Funeral!"
 
L

Les Cargill

Raj said:
Rather than
include <stdio.h> can I use int printf(const char *,...) correct at all
places if I only use printf in my program..

Cheers


It's better to use the #include. By "better", I mean that
those who read your code later will see something they're
more likely to expect.
 
R

Raj Pashwar

You *can*, but there's no good reason to do so.

It's permitted by 7.1.4p2 (7.1.7 in C89/C90):

Provided that a library function can be declared without reference
to any type defined in a header, it is also permissible to declare
the function and use it without including its associated header.

The <stdio.h> header exists precisely so you don't have write your own
declarations for standard functions. Using it guarantees (assuming your
implementation isn't broken) that the declarations will be correct. If
you write your own declarations, there's always a risk that you'll get
something wrong.

And in fact, you have. The declaration you show:

int printf(const char *,...);

is correct for C89/C90, but starting with C99 the declaration changed
to:

int printf(const char * restrict, ...);

(Omitting the "restrict" *probably* won't cause any problems, but it
could inhibit some optimizations.)

And even that works only because printf doesn't happen to depend on any
other declarations in <stdio.h>. You can't declare fprintf this way, for
example, because it depends on the definition of FILE -- and its
definition can vary substantially from one implementation to another.

Just write "#include <stdio.h>" and be done with it.

Thanks for the informations. Conclusion seems to be that my definition
will work fine though may be sub-optimal.

I see a few reasons to declare the function without the header, ie speeds
up compilation, also allows Principal of Data Hiding (localize
declaration to a block and prevent name leakage elsewhere).

Cheers,
Raj
 
E

Eric Sosman

[...]
Just write "#include <stdio.h>" and be done with it.

Thanks for the informations. Conclusion seems to be that my definition
will work fine though may be sub-optimal.

I see a few reasons to declare the function without the header, ie speeds
up compilation, also allows Principal of Data Hiding (localize
declaration to a block and prevent name leakage elsewhere).

Have you actually measured a compilation speedup? If so,
how many times must you compile just to recoup the time you've
spent reading and writing on this thread?

As for data hiding: For one thing, printf() is not data, but
a function. For another, an identifier with external linkage will
"leak" to the entire program no matter what you do!
 
K

Keith Thompson

Raj Pashwar said:
Raj Pashwar said:
Rather than
include <stdio.h> can I use int printf(const char *,...) correct at all
places if I only use printf in my program..

You *can*, but there's no good reason to do so. [30 lines deleted]
Just write "#include <stdio.h>" and be done with it.

Thanks for the informations. Conclusion seems to be that my definition
will work fine though may be sub-optimal.

That may be the conclusion that you drew, but it's certainly not
what I intended. More precisely, your statement is correct, but
not particularly useful.

In particular, if your implementation defines printf with the
"restrict" keyword, and you declare it without "restrict", it may
make your program's behavior undefined (I'd have to dig into the
wording in the standard to be sure). As I said, it's not likely to
affect your program's behavior in practice, but it could -- which
means you have one more thing to worry about when you're trying to
figure out why your program isn't working.
I see a few reasons to declare the function without the header, ie speeds
up compilation, also allows Principal of Data Hiding (localize
declaration to a block and prevent name leakage elsewhere).

You lose the advantages of possible variations in how the
implementation declares printf. The speed-up in compilation speed is
likely to be trivial (have you measured it?), and the time saved is
almost certainly a tiny fraction of the time we've spent discussing
it here. 99% of C programmers just write "#include <stdio.h>";
by doing it differently, you waste the time of anyone reading your
code, because they'll have to figure out what the heck you're doing.

As soon as you add a call to fprintf, you *have* to include the header
because it depends on the definition of FILE. The same applies to any
function that takes a FILE* argument.

Keep it simple. Just write "#include <stdio.h>".
 
P

Phil Carmody

Raj Pashwar said:
Rather than
include <stdio.h> can I use int printf(const char *,...) correct at all
places if I only use printf in my program..

If you have to ask the question, then, for everyone's safety, just use
the #include.

Phil
--
I'd argue that there is much evidence for the existence of a God.
Pics or it didn't happen.
-- Tom (/. uid 822)
 
P

Phil Carmody

Raj Pashwar said:
Thanks for the informations. Conclusion seems to be that my definition
will work fine though may be sub-optimal.

That's not what I've seen *anyone* recommend, so how can you conclude
that? I do know how how - because it was the answer you wanted, and
you have tacked on "may be sub-optimal" as a way of pretending that
you've paid attention to the answers you've been given by various
highly experienced C programmers. (We must have 100 years between us,
surely?)
I see a few reasons to declare the function without the header, ie speeds
up compilation,

I could probably have guessed, given that you asked the question that
you did, that you would also have some unfounded opinion on speed
optimisation. I had it too, for about 2 weeks after learning
C. Fortunately I grew out of it quickly.
also allows Principal of Data Hiding (localize
declaration to a block and prevent name leakage elsewhere).

That's not data hiding. That name is not permitted to exist anywhere
except as the standard library defines it, and everyone is permitted
to know what the standard library defines.

You're optimising the wrong thing. Write for future reading, not
for imaginary keyhole optimisations.

Phil
--
I'd argue that there is much evidence for the existence of a God.
Pics or it didn't happen.
-- Tom (/. uid 822)
 
P

Phil Carmody

Ben Bacarisse said:
The second point is rather odd because it conflicts with another: the
principle of least surprise. C programmer expect printf to be, well,
the global printf they know, so localising its declaration will surprise
your readers.

Dang. That's the kind of thing that was going through my head, but
my expression of the idea was pants. You've nailed it though.

Raj - listen to Ben, he speaks wise words.

Phil
--
I'd argue that there is much evidence for the existence of a God.
Pics or it didn't happen.
-- Tom (/. uid 822)
 
B

Ben Bacarisse

Raj Pashwar said:
Thanks for the informations. Conclusion seems to be that my definition
will work fine though may be sub-optimal.

I see a few reasons to declare the function without the header, ie speeds
up compilation, also allows Principal of Data Hiding (localize
declaration to a block and prevent name leakage elsewhere).

The second point is rather odd because it conflicts with another: the
principle of least surprise. C programmer expect printf to be, well,
the global printf they know, so localising its declaration will surprise
your readers.

Note that you posted here to ask. A good proportion of people reading
your code will not know the answer either. Do you want them to be
puzzled (or to have to take your /* honest, it's legal! */ comment at
face value)?
 
B

Ben Pfaff

Raj Pashwar said:
I see a few reasons to declare the function without the header, ie speeds
up compilation, also allows Principal of Data Hiding (localize
declaration to a block and prevent name leakage elsewhere).

You've got it backwards. The declaration of printf() is already
nicely hidden from you in <stdio.h>. You're trying to make it
visible.
 
T

Tim Rentsch

Raj Pashwar said:
Rather than
include <stdio.h> can I use int printf(const char *,...) correct at all
places if I only use printf in my program..

1. Yes.

2. There's a simple check you can do -- make a test file containing just

#include <stdio.h>
int printf(const char *,...);

and compile it (using a conforming mode, eg, 'gcc -ansi -pedantic',
and/or 'gcc -std=c99 -pedantic' (better, '-pedantic-errors' in both
cases). Observe that no warning or errors are produced.

3. If you are interested in other questions like this, it's worth
your while to get a copy of the C Standard document (or a very
close approximation to) and try to discover an answer yourself
by reading the relevant sections. Here are links for C99 and
C11, respectively:

http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf

Download them NOW!

4. Ignore the scare tactics of the naysayers implying that this
declaration of printf is somehow less reliable than just
including <stdio.h>. The declaration you give is absolutely
guaranteed to work. The idea that it will have some effect
on performance is conceivable but not likely, and even less
likely to be relevant.

5. Personally, I would tend to favor #include <stdio.h> over just
a bare declaration of printf() in almost all circumstances,
but that's a personal judgment, not a logical one. If you
think it's important to limit the scope of where printf() is
callable, using local declarations does (in C99 and C11)
provide a way of doing that. Although, if that's true,
probably it is worth separating out those functions that use
printf() and put them in a separate .c file, and include
<stdio.h> for that file. Try different possibilities, see
what provides the best overall balance.
 
T

Tim Rentsch

Keith Thompson said:
Raj Pashwar said:
Rather than
include <stdio.h> can I use int printf(const char *,...) correct at all
places if I only use printf in my program..

You *can*, but there's no good reason to do so. [30 lines deleted]
Just write "#include <stdio.h>" and be done with it.

Thanks for the informations. Conclusion seems to be that my definition
will work fine though may be sub-optimal.

That may be the conclusion that you drew, but it's certainly not
what I intended. More precisely, your statement is correct, but
not particularly useful.

In particular, if your implementation defines printf with the
"restrict" keyword, and you declare it without "restrict", it may
make your program's behavior undefined (I'd have to dig into the
wording in the standard to be sure). [snip]

Now that it is being pointed out, I'm confident you will
find the relevant passage or passages and post a correction.
 
T

Tim Rentsch

Eric Sosman said:
[...]
Just write "#include <stdio.h>" and be done with it.

[snip]
I see a few reasons to declare the function without the header, ie speeds
up compilation, also allows Principal of Data Hiding (localize
declaration to a block and prevent name leakage elsewhere).

[snip] an identifier with external linkage will
"leak" to the entire program no matter what you do!

Not in the sense that he means it, ie, the declaration
will be visible only in the scope (or scopes) where
it is declared. It won't be visible in other (non-nested)
scopes. In C99, that would mean other uses of printf()
would cause compilation errors.
 
P

Phil Carmody

Tim Rentsch said:
....
4. Ignore the scare tactics of the naysayers implying that this
declaration of printf is somehow less reliable than just
including <stdio.h>. The declaration you give is absolutely
guaranteed to work. The idea that it will have some effect
on performance is conceivable but not likely, and even less
likely to be relevant.

4b. Ignore the scare tactics of those who tell you, once you've
included stdlib.h, to write:

type_t *p = malloc(sizeof(*p));

rather than:

type_t *p = (type_t *)malloc(sizeof(type_t));

The former is absolutely guaranteed to work.


Good advice, no? I'm tempted to say a cost-risk-benefit analysis
would favour my advice even more than yours, given what I've
actually seen go wrong over the decades. E.g. gcc's format mismatch
warnings trap many portability gotchas as well as grosser bugs -
cost zero, risk zero, benefit palpable.

Phil
--
I'd argue that there is much evidence for the existence of a God.
Pics or it didn't happen.
-- Tom (/. uid 822)
 
T

Tim Rentsch

Phil Carmody said:
also allows Principal of Data Hiding (localize
declaration to a block and prevent name leakage elsewhere).

That's not data hiding. That name is not permitted to exist anywhere
except as the standard library defines it, [snip[

That's not exactly right. Defining a library function (such
as printf()) yourself is undefined behavior, but the Standard
doesn't actually disallow it. There are lots of implementations
where defining a library function yourself will work fine,
and "override" the standard function, by means of weak symbol
table entries in standard library object modules.

I admit this distinction goes beyond what the OP was asking
about, but I think it's important to give correct statements
and not gloss over these kinds of distinctions, even though
they might seem minor relative to the question being asked.
 
T

Tim Rentsch

Ben Bacarisse said:
The second point is rather odd because it conflicts with another: the
principle of least surprise.

Not that this matters really, but historically the Law of Least
Astonishment (as it used to be called) arose in connection with
the design of programming languages rather than the design of
programs (assuming my memory on the subject is correct, which it
may not be). So the allusion to it here caused (for me at least)
the more general principle to be violated.
C programmer expect printf to be, well, the global printf they
know, so localising its declaration will surprise your readers.

Will it? If I saw a local declaration of printf(), I think I
would assume the writer wanted to limit the scope of where the
identifier will be used, just like any other declaration. Is
there reason to believe his readers are confused on this point?
I don't see any reason a priori to expect they will be.
Note that you posted here to ask. A good proportion of people
reading your code will not know the answer either. Do you want
them to be puzzled (or to have to take your /* honest, it's
legal! */ comment at face value)?

Oh, but his question is a little bit different, namely, is this
the right way to write the declaration? The readers don't need
to worry (and probably won't worry) about that question, since
he is giving them (presumably) a working program. It's possible
of course that some of them will wonder about whether it's legal,
and take the trouble to find out, but that doesn't strike me as
a bad thing; it's only when unwary readers are confused that I
think some sort of advisory is called for, but to me that doesn't
seem to be the case here.
 
T

Tim Rentsch

Ben Pfaff said:
You've got it backwards. The declaration of printf() is already
nicely hidden from you in <stdio.h>. You're trying to make it
visible.

Actually what he wants is to _limit_ the visibility to something
smaller than file scope. To do that, it is necessary to declare
printf() directly, since doing a #include has defined behavior only
outside of all external defintions (and in particular, outside of
any function body).
 
K

Keith Thompson

Tim Rentsch said:
Keith Thompson said:
Raj Pashwar said:
On Wed, 18 Jul 2012 14:09:01 -0700, Keith Thompson wrote:
Rather than
include <stdio.h> can I use int printf(const char *,...) correct at all
places if I only use printf in my program..

You *can*, but there's no good reason to do so. [30 lines deleted]
Just write "#include <stdio.h>" and be done with it.

Thanks for the informations. Conclusion seems to be that my definition
will work fine though may be sub-optimal.

That may be the conclusion that you drew, but it's certainly not
what I intended. More precisely, your statement is correct, but
not particularly useful.

In particular, if your implementation defines printf with the
"restrict" keyword, and you declare it without "restrict", it may
make your program's behavior undefined (I'd have to dig into the
wording in the standard to be sure). [snip]

Now that it is being pointed out, I'm confident you will
find the relevant passage or passages and post a correction.

Not exactly.

The OP's declaration of printf is:

int printf(const char *,...);

That's compatible with the C89/C90 standard declaration of printf:

int printf(const char *format, ...);

but the C99 (and later) declaration is:

int printf(const char *restrict format, ...);

I'll refer to N1570.

6.5.2.2p6 (Function calls):

If the function is defined with a type that includes a prototype,
and either the prototype ends with an ellipsis (, ...) or the
types of the arguments after promotion are not compatible with
the types of the parameters, the behavior is undefined.

6.7.3p10 (Type qualifiers):

For two qualified types to be compatible, both shall have the
identically qualified version of a compatible type; the order
of type qualifiers within a list of specifiers or qualifiers
does not affect the specified type.

("restrict" is a type qualifier.)

6.7.6p2 (Declarators):

Each declarator declares one identifier, and asserts that
when an operand of the same form as the declarator appears
in an expression, it designates a function or object with the
scope, storage duration, and type indicated by the declaration
specifiers.

So the types "const char*" and "const char *restrict" are not
compatible, and therefore the function types are incompatible.
In fact, 6.7.6p2 requires them to be the same type, not merely
compatible. (So I didn't really need 6.5.2.2p6 or 6.7.3p10, but
I had already copy-and-pasted them, so I'll leave them here.)

My interpretation of all this is that a call to printf in the scope
of a declaration

int printf(const char*, ...);

has well defined behavior in C89/C90, but undefined behavior in
C99 and C11.

(For most implementations, I would expect the consequence to be that
the call works just as it would if printf were declared correctly.)

I also conclude that this (which you suggested elsewhere in this
thread):

#include <stdio.h>
int printf(const char *, ...);

or this:

int printf(const char *restrict, ...);
int printf(const char *, ...);

violates the constraint in 6.7p4:

All declarations in the same scope that refer to the same object
or function shall specify compatible types.

gcc fails to diagnose this, though it does complain if one of the
declarations is missing the "const".

There is a counterargument to all this. 6.2.5p26 says:

The qualified or unqualified versions of a type are distinct
types that belong to the same type category and have the same
representation and alignment requirements.

with a footnote:

The same representation and alignment requirements are meant
to imply interchangeability as arguments to functions, return
values from functions, and members of unions.

Is that what you had in mind?

So by declaring printf yourself (without the "restrict" rather
than including <stdio.h>, you are at worst invoking undefined
behavior, and at best depending on a potentially ambiguous line
of reasoning -- and imposing that line of reasoning on anyone who
reads or maintains the code. It *might* save some time by avoiding
having to process <stdio.h> (surely a tiny fraction of the time
we've spent debating it). And it doesn't extend to functions that
depend on the declaration of FILE.

Or you can just write "#include <stdio.h>", which is *much*
easier, guaranteed to be correct, and consistent with what 99%
of C programmers use and expect.
 

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
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top