When using a int to float implicit conversion, it fails with printf()
#include <stdio.h>
int main(int argc, char **argv) {
float s = 10.0;
printf("%f %f %f %f\n", s, 0, s, 0);
return 0;
}
when compiled with gcc -g scale.c -o scale
it does output garbage
./scale
10.000000 10.000000 10.000000 -5486124068793688683255936251187209270074392635932332070112001988456197381759672947165175699536362793613284725337872111744958183862744647903224103718245670299614498700710006264535590197791934024641512541262359795191593953928908168990292758500391456212260452596575509589842140073806143686060649302051520512.000000
If I explicitly cast the integer to float, or use a 0.0
(which is a double
) it works as designed.
#include <stdio.h>
int main(int argc, char **argv) {
float s = 10.0;
printf("%f %f %f %f\n", s, 0.0, s, 0.0);
return 0;
}
when compiled with gcc -g scale.c -o scale
it does output the expected output
./scale
10.000000 0.000000 10.000000 0.000000
What is happening ?
I'm using gcc (Debian 10.2.1-6) 10.2.1 20210110
if that's important.
The conversion specifier f
expects an object of the type double
. Usually sizeof( double )
is equal to 8
while sizeof( int )
is equal to 4
. And moreover integers and doubles have different internal representations.
Using an incorrect conversion specifier results in undefined behavior.
From the C Standard (7.21.6.1 The fprintf function)
9 If a conversion specification is invalid, the behavior is undefined.275) If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.
As for objects of the type float
then due to default argument promotions they are converted to the type double
.
From the C Standard (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.
So these calls of printf
printf("%f %f %f %f\n", s, 0.0, s, 0.0);
and
printf("%f %f %f %f\n", s, 0.0f, s, 0.0f);
are equivalent relative to the result.
Pay attention to that some programmers to output doubles use the length modifier l
in conversion specification as for example %lf
. However the length modifier has no effect and should be removed.