versions of the standard. For the foreseeable future both styles will coexist, because of the volume of
pre-ANSI code. So, if prototypes are "a good thing," should we use them everywhere, and go back and
add prototypes to existing code when we conduct maintenance on it? Emphatically not!
Function prototypes not only change the syntax of the language; they also introduce a subtle (and
arguably undesirable) difference into the semantics. As we know from the previous section, under
K&R, if you passed anything shorter than an int to a function it actually got an int, and floats were
expanded to doubles. The values are automatically trimmed back to the corresponding narrower types
in the body of the called function, if they are declared that way there.
At this point, you might be wondering, why bother expanding them at all, only to shrink them back? It
was originally done to simplify the compiler—everything became a standard size. With just a few
types it especially simplified argument passing, especially in very old K&R C where you couldn't pass
structs as arguments. There were exactly three types: int, double, and pointer. All arguments became a
standard size, and the callee would narrow them if necessary.
In contrast, if you use a function prototype, the default argument promotions do not occur. If you
prototype something as a char, a char actually gets passed. If you use the new-style function
definition (where argument types are given in the parentheses following the function name), then the
compiler generates code on the assumption that the parameters are exactly as declared, without the
default type widening.
Where Prototypes Break Down
There are four cases to consider here:
- K&R function declaration, and K&R function definition
call works ok, promoted types are passed
- ANSI C declaration (prototype), and ANSI C definition
call works ok, actual types are passed
- ANSI C declaration (prototype), and K&R function definition
Failure if you use a narrow type! Call passes actual
types, function expects promoted types.
- K&R function declaration, and ANSI C definition