The C standard states that, for a function definition, if the declarator includes an identifier list, the types of the parameters shall be declared in a following declaration list. Apparently this makes a difference.
extern int max(int a, int b)
{
return a > b ? a : b;
}
extern int max(a, b)
int a, b;
{
return a > b ? a : b;
}
Here int a, b; is the declaration list for the parameters. The
difference between these two definitions is that the first form acts
as a prototype declaration that forces conversion of the arguments of
subsequent calls to the function, whereas the second form does not.
What does this mean for the programmer and does it affect the code the compiler produces?
It means that in the second case, it’s the responsibility of the caller to ensure that the arguments provided are of the correct type; no implicit conversion will be provided (other than the default argument promotions). From section 6.5.2.2:
So calling code like this will be ok:
because
xandyare promoted tointbefore being placed on the stack.However, code like this will not be ok:
xandywill be placed on the stack asdoubleandlong, butmax()will attempt to read twoints, which will result in undefined behaviour (in practice, the raw bits will be reinterpreted).This is one reason not to use the second form; the only reason it’s in the standard is to provide backward compatibility with (extremely) legacy code. If you’re using GCC, you can enforce this by using the
-Wold-style-definitionflag; I would hope that other compilers would offer something equivalent.