What is the behavior of printf() when we supply multiple arguments to it without a format specifier?
Example:
int main()
{
printf("hello", "hi");
return 0;
}
Why does the compiler produce a warning on compilation of the above program? :
warning: too many arguments for format [-Wformat-extra-args]
If we compile the similar program below:
int main()
{
char *s1 = "hello";
char *s2 = "hi";
printf(s1, s2);
}
No warnings are produced. What is the reason for this?
Also, why do both programs output hello only, and don't also print hi?
The C 2018 standard specifies the behavior of printf in clause 7.21.6.3, in which paragraph 2 says “The printf function is equivalent to fprintf with the argument stdout interposed before the arguments to printf.”
The standard specifies the behavior of fprintf in 7.21.6.1, which tells us the second argument (the first argument of printf) is a format string and that it may contain various conversion specifications introduced by the character “%”. Thus, in printf("hello", "hi"), "hello" is a format string with no conversion specifications. In this case, paragraph 2 tells us what happens:
If the format is exhausted [fully processed] while arguments remain, the excess arguments are evaluated (as always) but are otherwise ignored.
Thus, in printf("hello", "hi"), "hi" is ignored, and "hello" is a format string that contains only ordinary characters, which are copied to the output stream per paragraph 3.
The compiler warns about printf("hello", "hi") because it is able to see that this call contains an excess argument because the format string does not contain a conversion specification for it.
Your compiler does not warn about printf(s1,s2); because it does not analyze what s1 will contain during this call. This sort of analysis is not impossible in this situation, but situations like this are rare: When a programmer uses a pointer to a string as the format string for printf, it is usually a string or pointer that is computed, constructed, or selected during program execution, and the manner of this computation is often beyond the ability of a compiler to analyze. Situations where the pointer is clearly a pointer to a fixed string are rare, since they are not frequently useful, so presumably compiler implementors have not found it valuable to implement the code necessary for the compiler to handle these situations.
printf() are ignored.The official C language standard (the link is to a draft of the C11 version) says the following:
§ 7.21.6.1 The
fprintffunction
...
... If the format is exhausted while arguments remain, the excess arguments are evaluated (as always) but are otherwise ignored. The
fprintffunction returns when the end of the format string is encountered.
... and printf() is simply fprintf() targeted at the standard output file.
About your two code snippets:
The compiler is giving you a hint, for the first snippet, that the number of arguments doesn't match the number of specifiers in the format string. It's just a courtesy - it's not required to notice this. This also explains why the compiler does not notice it for the second snippet. It could, but it's too much effort to chase your pointers and check what they point at.
In both cases, your format string is your first argument to printf(), i.e. "hello". That string has no format specifiers, so the printf() looks at the "hello", and understands it only needs to print that and doesn't need process any other arguments. That's whi it ignores "hi".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With