This means that in the second case, the caller's responsibility is to ensure that the arguments provided are of the correct type; Implicit conversion will not be implied (except for promotions by default). From section 6.5.2.2:
If the expression denoting the called function is of a type that does not include the prototype, entire promotions are executed for each argument.
...
If the expression that denotes the called function is of a type that includes the prototype, the arguments are implicitly converted, as if they were assigned, the types have the appropriate parameters.
So caller code like this will be fine:
char x = 3; char y = 7; max(x, y);
because x
and y
pushed to int
before being pushed onto the stack.
However, code like this will be out of order:
double x = 3.0; long y = 7; max(x, y);
x
and y
will be pushed onto the stack as double
and long
, but max()
will try to read two int
s, which will lead to undefined behavior (in practice, the original bits will be reinterpreted).
This is one reason not to use the second form; the only reason the standard is backward compatible with (extremely) legacy code. If you use GCC, you can apply this using the -Wold-style-definition
flag; I hope other compilers would suggest something equivalent.
Oliver Charlesworth
source share