I was studying about default argument promotions and got stuck at one point. In C 2011 (ISO/IEC 9899:2011), the relevant part seem to be:
§6.5.2.2 Function calls
¶6 If the expression that denotes the called function has a type that does not include a prototype, the integer promotions are performed on each argument, and arguments that have type float are promoted to double. These are called the default argument promotions. If the number of arguments does not equal the number of parameters, the behavior is undefined. If the function is defined with a type that includes a prototype, and either the prototype ends with an ellipsis (, ...) or the types of the arguments after promotion are not compatible with the types of the parameters, the behavior is undefined. If the function is defined with a type that does not include a prototype, and the types of the arguments after promotion are not compatible with those of the parameters after promotion, the behavior is undefined, except for the following cases:
— one promoted type is a signed integer type, the other promoted type is the corresponding unsigned integer type, and the value is representable in both types;
— both types are pointers to qualified or unqualified versions of a character type or void.
In the last three lines of paragraph it talks about the function type that does not include a prototype while defining it.
It says if the types of the arguments after promotion are not compatible with those of the parameters after promotion, the behavior is undefined.
Now i have a very silly doubt that if both the function declaration and function definition does not include a prototype as mentioned in this paragraph, so about which parameters they are talking about in last three lines of paragraph. And what is the meaning of "parameters after promotion" here as i have only studied about argument promotions. What is "parameter promotions"?
Also can you give example of the exceptional cases mentioned in the last. If someone can explain this with a proper example that would be really appreciable.
Before C was standardized (aka before C89), functions were defined differently. The style is still supported in C11 for backwards-compatibility. Don't use it unless the whole purpose is to have fun:
In a way, these functions have parameters that behave like varargs. The caller doesn't know what parameters the function expects (same as with varargs). It is able to pass it any parameters and any number of them. However, it is of course undefined behavior if the number of parameters in the call statement doesn't match the number of parameters in the declaration.
Of course, there is a problem that arises from this. If the caller wants to pass a
short, how will it know whether the function is expecting ashort(and pass it directly) or anint(and needs to convert it)? It cannot, so a common ground was reached. It has been decided that:charandshortget promoted tointfloatgets promoted todoubleThis happens for all functions defined this way (K&R style) and for varargs parameters. This way, a K&R function will never expect a
shortparameter, thus the compiler will always promoteshortparameters toint.Of course, as @aschepler said, you can still define the function like:
This means that the parameters are first converted to
intand passed to the function and only then does the function convert them toshortand add them.Be careful with functions like
printf():You may actually see K&R functions quite often, especially if the author didn't pay attention to add the
voidkeyword to a function that takes no parameters:EDIT: Not sure why, but cppreference classifies functions defined like f1() as their own type of function (parameter-less without
void), instead of K&R functions. I don't have the standard in front of me, but even if the standard says the same thing, they should behave the same and they have the history I mentioned.Default argument promotions
Function declarations in C