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.