I was reading C standard for default argument promotions and got confused over many points. This question shows all the paragraphs that i have doubt on in a proper way.
First of all in Paragraph 6 point 3, it says if the prototype ends with ellipsis the behavior is undefined. Now my doubt is that if we talk about printf
, it's prototype also ends with ellipsis but it's behavior is not undefined and in fact it follows the point 1 of paragraph 6. What the standard is trying to explain here? and further it says that if types of the arguments after promotion are not compatible with the types of the parameters, the behavior is undefined.. Now here my doubt is that if parameters are already declared in the function prototype why in first place arguments are getting promoted.
Than in paragraph 6 point 4,it says that the types of the arguments after promotion are not compatible with those of the parameters after promotion, the behavior is undefined. As here, it is mentioned that the function do not have a prototype, So exactly about what parameters they are talking about ? and how parameters get promoted. I have only studied about argument promotions.
Than in paragraph 7 point 1 what does this line mean : taking the type of each parameter to be the unqualified version of its declared type.
I am having really a very hard time understanding all this. It would be really helpful if you can explain all points with proper examples one by one. I am non native English speaker, if i am misunderstanding some standard's points, please point that mistakes too.
In C 1999 clause 6.5.2.2 paragraph 6, the item labeled 3 in that question is intended to be interpreted with the item labeled 1: If the calling expression use a type that does not have a prototype, and the called function is defined with a prototype that ends with an ellipsis or the promoted arguments types are incompatible with the parameter types, then the behavior is undefined.
So this is not saying you cannot use ellipsis, just that there can be a conflict between the function type used in an expression that calls a function and the function type used in defining the function.
Example:
File Caller.c contains:
void foo(); // No prototype (parameter types are not declared).
int main(void)
{
foo(3, 4);
}
File Function.c contains:
void foo(int x,...) // Prototype (parameter types are declared) and has ellipsis.
{
}
The behavior is undefined because foo
is called as if it were void foo()
, but it is defined with void foo(int x,...)
. This mismatch should not occur in modern practice, because declaring functions without prototypes is old-style. It is still supported in C so that old source code can still be compiled, but new source code should not use it. As long as parameter types are always declared, in both function declarations and function definitions, then this situation will never occur.
In paragraph 7, “taking the type of each parameter to be the unqualified versio of its declared type” means to ignore the qualifiers (const
, volatile
, restrict
, or _Atomic
). This means it is okay to pass an int
argument for a const int
parameter, and so on.