Daniel Nichols wrote:
Thanks everybody for feedback.
[...]
It's just Eric Sosman states it is good practice to declare a function
before use. Is it because, if you do prototype explicitly you can
position the function physically anywhere in the file?
Under C99 rules, every function must be declared before
the first reference to it. Under C89, a preceding declaration
can be omitted if the function returns `int' and has an argument
list compatible with the K&R form; all other functions must be
declared before use, even in C89.
There are a couple of reasons why it's "good practice" to
declare before use even when C89 would let you get away without
it. First, there's the likelihood that you will someday want
to move the code to a C99 environment, where the declaration
becomes mandatory. Second, no "variadic" function has a K&R-
compatible argument list (the `...' can't be expressed in K&R),
so it follows that every variadic function must be pre-declared.
Third, it's surprisingly difficult to determine whether a given
function has a K&R-compatible argument list! For example,
int a(size_t x) { ... }
int b(time_t x) { ... }
int c(char x) { ... }
int d(enum foo x) { ... }
may be K&R-compatible on some implementations but not on others.
"Good practice" quite often amounts to little more than
avoiding unpleasant surprises.
The advantage of writing pure declarations (the above, but
replacing each `{ ... }' with `;') is that if you stick 'em all
somewhere near the top of the file you can then arrange the
actual function definitions in whatever order makes it easiest
for you to read. The disadvantage, as you noted in some text I
snipped, is that when you write both a declaration and a definition
you are repeating yourself and thus have the opportunity to
contradict yourself -- the compiler will complain about the
contradiction, but it's an error that simply can't arise if you use
the "Pascal style."
And, of course, there are some situations where declarations
are unavoidable. Mutually recursive functions, for example:
double a(void) {
...
x = b();
}
double b(void) {
...
y = a();
}
.... cannot be made to work without introducing a declaration
of b() separate from its definition.
Obviously, things work as they are but I don't want to have to go and
duplicate prototypes up at some later time after a code review from
someone who thinks prototypes are essential and required for C99.
You're still confusing "declaration" and "prototype."
Function declarations (remember, a definition is also a
declaration) are sometimes required and sometimes optional
in C89, are always required in C99, and are always good
practice under either Standard. Argument-list prototypes
are mandatory for variadic (`...') functions and for functions
that accept "narrow" argument types (`float' and usually some
others), optional for fixed-list functions with "wide"
arguments, and good practice always, under both Standards.
Here are two function definitions (and declarations),
one with a prototype and one without:
double f(int a, float b, char *c)
{ ... }
double g(a, b, c)
int a;
float b;
char *c;
{ ... }
Here are correct declarations of these functions, using
prototypes:
double f(int, float, char*);
double g(int, double, char*);
Note the declared type of the second argument to g(). It's
hard in general to get this right, and that's one reason
not to mix'n'match ANSI prototypes with K&R functions.
Here is a correct declaration of g(), with no prototype:
double g();
It is not possible to declare f() correctly without using
a prototype -- which is a reason not to mix'n'match ANSI
function definitions with K&R prototypeless declarations.
--
Er*********@sun.com