#include <stdio.h>
int main(void)
{
short i = 1;
printf("%hd\n", i);
printf("%hd\n", i * i);
return 0;
}
Compiling this gives the warning warning: format specifies type 'short' but the argument has type 'int' [-Wformat] printf("%hd\n", i * i);
.
Removing the printf("%hd\n", i * i);
statement produces no warning.
Have I done something wrong? It is my understanding that since i
has type short int
that the value of the expression i * i
has type short int
but then printf
performs an integer promotion to convert this short int
result to int
form before converting this int
to short
again (due to the conversion specifier).
I don't particularly see what is wrong about the code though. Is it just a warning telling me to be careful of the possibility that a more complicated expression than a simple short int
variable being passed as an argument to printf
corresponding to the %hd
conversion specifier might result in overflow? Thanks!
In i * i
the arguments to the multiplication undergo "integer promotions" and "usual arithmetic conversions" and become int
before the multiplication is done. The final result of the multiplication is an int.
The type of i * i
is int
(when type of i
is int
, short
, char
, or _Bool
).
When you call printf with "%hd"
the corresponding argument should be a short
. What happens is that it is automatically converted to int
and it's an int
that printf sees. The internal code of printf will convert that int
to a short
to do its thing.
Problem is if you start with an int
value outside the range of short
.
short i = SHRT_MAX;
int j = i * i;
short k = i * i; // overflow while assigning
printf("%hd %hd", j, k);
// ^ (kinda) overflow inside the innards of printf