|
|
In order for function prototype declarations to work with old-style function definitions, both must specify functionally identical interfaces (or have ``compatible types'' using ANSI C's terminology).
For functions with varying arguments, there can be no mixing of ANSI C's ellipsis notation and the old-style varargs() function definition. For functions with a fixed amount of parameters, however, you can simply specify the types of the parameters as they were passed in previous implementations.
In pre-ANSI C compilers, each argument was converted just before it was passed to the called function according to the default argument promotions. These specified that all integral types narrower than int were promoted to int size, and any float argument was promoted to double. This simplified both the compiler and libraries. Function prototypes are more expressive -- the specified parameter type is what is passed to the function. Thus, if a function prototype is written for an existing (old-style) function definition, there should be no parameters in the function prototype with any of the following types:
char signed char unsigned char float short signed short unsigned shortThere still remain two complications with writing prototypes: typedef names and the promotion rules for narrow unsigned types.
If parameters in old-style functions were declared using typedef names such as off_t and ino_t, it is important to know whether or not the typedef name designates a type that is affected by the default argument promotions. For these two, off_t is a long, so it is appropriate to use in a function prototype, but ino_t used to be an unsigned so if it were used in a prototype, the compiler would issue a diagnostic (possibly fatal) because the old-style definition and the prototype specify different and incompatible interfaces.
Just what should be used instead of an unsigned short leads us into the final complication. The one biggest incompatibility between pre-ANSI C compilers and ANSI C is the promotion rule for the widening of unsigned char and unsigned short to an int-sized value. (See ``Promotions: unsigned vs. value preserving''). Unfortunately, the parameter type that matches such an old-style parameter depends on the compilation mode used when you compile: for -Xt, unsigned int should be used; -Xa and -Xc should use int. The best approach (even though it violates the spirit of choices 2 and 3 above) is to change the old-style definition to specify either int or unsigned int and use the matching type in the function prototype (you can always assign its value to a local variable with the narrower type, if necessary, after you enter the function).