A function prototype is a function declaration that specifies the data types of its arguments in the parameter list. The compiler uses the information in a function prototype to ensure that the corresponding function definition and all corresponding function declarations and calls within the scope of the prototype contain the correct number of arguments or parameters, and that each argument or parameter is of the correct data type.
Prototypes are syntactically distinguished from the old style of function declaration. The two styles can be mixed for any single function, but this is not recommended. The following is a comparison of the old and the prototype styles of declaration:
Old style:
Prototype style:
void
keyword.
A function prototype has the following syntax:
declaration-specifiers(opt) declarator;
The declarator includes a parameter type list, which can
consist of a single parameter of type void
. In its
simplest form, a function prototype declaration might have the
following format:
storage_class(opt) return_type(opt) function_name ( type(1) parameter(1), ..., type(n) parameter(n) );
Consider the following function definition:
char function_name( int lower, int *upper, char (*func)(), double y ) { }
The corresponding prototype declaration for this function is:
char function_name( int lower, int *upper, char (*func)(), double y );
A prototype is identical to the header of its corresponding function definition specified in the prototype style, with the addition of a terminating semicolon (;) or comma (,), as appropriate (depending on whether the prototype is declared alone or in a multiple declaration).
Function prototypes need not use the same parameter identifiers as in the corresponding function definition because identifiers in a prototype have scope only within the identifier list. Moreover, the identifiers themselves need not be specified in the prototype declaration; only the types are required.
For example, the following prototype declarations are equivalent:
char function_name( int lower, int *upper, char (*func)(), double y ); char function_name( int a, int *b, char (*c)(), double d ); char function_name( int, int *, char (*)(), double );
Though not required, identifiers should be included in prototypes to improve program clarity and increase the type-checking capability of the compiler.
Variable-length argument lists are specified in function prototypes with ellipses. At least one parameter must precede the ellipses. For example:
char function_name( int lower, ... );
Data-type specifications cannot be omitted from a function prototype.
Prototypes must be placed appropriately in each compilation unit of a program. The position of the prototype determines its scope. A function prototype, like any function declaration, is considered within the scope of a corresponding function call only if the prototype is specified within the same block as the function call, any enclosing block, or at the outermost level of the source file. The compiler checks all function definitions, declarations, and calls from the position of the prototype to the end of its scope. If you misplace the prototype so that a function definition, declaration, or call occurs outside the scope of the prototype, any calls to that function behave as if there were no prototype.
The syntax of the function prototype is designed so that you can
extract the function header of each of your function definitions,
add a semicolon (;), place the prototypes in a header, and include
that header at the top of each compilation unit in your program. In
this way, function prototypes are declared to be external, extending
the scope of the prototype throughout the entire compilation
unit. To use prototype checking for C library function calls,
place the #include
preprocessor directives for the
.h
files appropriate for the library functions used in
the program.
It is an error if the number of arguments in a function definition, declaration, or call does not match the prototype.
If the data type of an argument in a function call does not match the corresponding type in the function prototype, the compiler tries to perform conversions. If the mismatched argument is assignment- compatible with the prototype parameter, the compiler converts the argument to the data type specified in the prototype, according to the argument conversion rules (see Section 5.6.1).
If the mismatched argument is not assignment-compatible with the prototype parameter, an error message is issued.