Villy said:
In GNU and other open source for unix you often see something like:
#if USE_ANSI_PROTOTYPE
int func (int a, int b);
#else
int func ();
#endif
int func (a, b)
int a;
int b;
{
...
}
Despite its apparent simplicity, this approach can be
difficult to use correctly. It's fine if all the arguments
are `int' (as in your example) or `double' or pointers or
structs or unions -- but if they're `char' or `unsigned short'
or `time_t' or ... The problem is that these types may be
subject to the default argument promotions when passed to a
K&R function, and you don't know at coding time whether they're
promotable, nor to what.
As a concrete example, try writing a prototype for
enum Cubs { TINKER, EVERS, CHANCE };
double play(x)
enum Cubs x;
{...}
To write the prototype, you need to discover what type
an `enum Cubs' argument will promote to. Since the compiler
can choose any integer type at all to represent `enum Cubs'
and since the promotion rules for the integer types are, to
some extent, implementation-dependent (e.g., `unsigned short'
promotes to `int' on some systems, `unsigned int' on others),
you find yourself in the uncomfortable position of trying to
out-guess every compiler that will ever process the code.
The upshot is that the only declaration for play()
you can be utterly confident in is
double play();
.... which loses, er, "some" of the benefits of prototypes.
Anything else risks lying to the compiler -- and we all
know what happens, sooner or later, when you lie to the
compiler.