Function Prototypes and Argument Coercion

A function prototype (also called a function declaration) tells the compiler the name of a function, the type of data returned by the function, the number of parameters the function expects to receive, the types of those parameters and the order in which the parameters of those types are expected.

Software Engineering Observation 6.6

Function prototypes are required in C++. Use #include preprocessor directives to obtain function prototypes for the C++ Standard Library functions from the header files for the appropriate libraries (e.g., the prototype for math function sqrt is in header file ; a partial list of C++ Standard Library header files appears in Section 6.6). Also use #include to obtain header files containing function prototypes written by you or your group members.

Common Programming Error 6.3

If a function is defined before it is invoked, then the function's definition also serves as the function's prototype, so a separate prototype is unnecessary. If a function is invoked before it is defined, and that function does not have a function prototype, a compilation error occurs.

Software Engineering Observation 6.7

Always provide function prototypes, even though it is possible to omit them when functions are defined before they are used (in which case the function header acts as the function prototype as well). Providing the prototypes avoids tying the code to the order in which functions are defined (which can easily change as a program evolves).

 

Function Signatures

The portion of a function prototype that includes the name of the function and the types of its arguments is called the function signature or simply the signature. The function signature does not specify the function's return type. Function in the same scope must have unique signatures. The scope of a function is the region of a program in which the function is known and accessible. We'll say more about scope in Section 6.10.


Common Programming Error 6.4

It is a compilation error if two functions in the same scope have the same signature but different return types.

In Fig. 6.3, if the function prototype in line 17 had been written

void maximum( int, int, int );

the compiler would report an error, because the void return type in the function prototype would differ from the int return type in the function header. Similarly, such a prototype would cause the statement

cout << maximum( 6, 9, 0 );

to generate a compilation error, because that statement depends on maximum to return a value to be displayed.

Argument Coercion

An important feature of function prototypes is argument coercioni.e., forcing arguments to the appropriate types specified by the parameter declarations. For example, a program can call a function with an integer argument, even though the function prototype specifies a double argumentthe function will still work correctly.

Argument Promotion Rules

Sometimes, argument values that do not correspond precisely to the parameter types in the function prototype can be converted by the compiler to the proper type before the function is called. These conversions occur as specified by C++'s promotion rules. The promotion rules indicate how to convert between types without losing data. An int can be converted to a double without changing its value. However, a double converted to an int truncates the fractional part of the double value. Keep in mind that double variables can hold numbers of much greater magnitude than int variables, so the loss of data may be considerable. Values may also be modified when converting large integer types to small integer types (e.g., long to short), signed to unsigned or unsigned to signed.

The promotion rules apply to expressions containing values of two or more data types; such expressions are also referred to as mixed-type expressions. The type of each value in a mixed-type expression is promoted to the "highest" type in the expression (actually a temporary version of each value is created and used for the expressionthe original values remain unchanged). Promotion also occurs when the type of a function argument does not match the parameter type specified in the function definition or prototype. Figure 6.6 lists the fundamental data types in order from "highest type" to "lowest type."

Figure 6.6. Promotion hierarchy for fundamental data types.

(This item is displayed on page 250 in the print version)

Data types

long double

 

double

 

float

 

unsigned long int

(synonymous with unsigned long)

long int

(synonymous with long)

unsigned int

(synonymous with unsigned)

int

 

unsigned short int

(synonymous with unsigned short)

short int

(synonymous with short)

unsigned char

 

char

 

bool

 

Converting values to lower fundamental types can result in incorrect values. Therefore, a value can be converted to a lower fundamental type only by explicitly assigning the value to a variable of lower type (some compilers will issue a warning in this case) or by using a cast operator (see Section 4.9). Function argument values are converted to the parameter types in a function prototype as if they were being assigned directly to variables of those types. If a square function that uses an integer parameter is called with a floating point argument, the argument is converted to int (a lower type), and square could return an incorrect value. For example, square( 4.5 ) returns 16, not 20.25.


Common Programming Error 6.5

Converting from a higher data type in the promotion hierarchy to a lower type, or between signed and unsigned, can corrupt the data value, causing a loss of information.

Common Programming Error 6.6

It is a compilation error if the arguments in a function call do not match the number and types of the parameters declared in the corresponding function prototype. It is also an error if the number of arguments in the call matches, but the arguments cannot be implicitly converted to the expected types.

Категории