printf("%f", 20);
results in the output 0.000000
, not 20.000000
. I'm guessing this has to do with how an int is represented in memory and how a double is represented in memory. Surprisingly for me, no matter how I alter 20
, for example by making the number larger, the output is still 0.000000
. Could someone please explain the underlying mechanics of this?
First of all, this is undefined behavior . %f
expects an argument of type float
/ double
. Passing an int
makes incompatible type and hence it invokes UB.
Quoting C11
, chapter §7.21.6.1, fprintf()
f
,F
A
double
argument representing a floating-point number [...]
a float
is also allowed, as due to default argument promotion rule, it will get promoted to a double
which is the expected type there, so either a double
or a float
is acceptable, but not an int
.
...and that's all. UB, is, well, UB. You cannot try to justify anything with a code producing UB.
That said, with proper warning levels enabled, the code should not compile, at all. Though, if you choose to make the code compile and produce a binary/assembly code you can see different code generated for different platforms. One of such cases is explained in the other answer by Matteo Italia , considering x86_64 arch on Linux/OS X.
Most probably you are compiling your code on a platform/ABI where even for varargs functions data is passed into registers, and in particular different registers for integer/floating point values. x86_64 on Linux/OS X behaves like that.
The caller has an integer to pass, so it puts it into rsi
; on the other side, printf
expects a floating point value, so it tries to read it from xmm0
. No matter how you change your integer argument to any other value printf
will be unaffected - if will just print whatever happens to stay into xmm0
at the moment of the call.
You can actually check if this is the case by changing your call to:
printf("%f", 20, 123.45);
if it's working as I described, you should see 123.45 printed (the caller here puts 123.45 into xmm0
, as it is the first floating point parameter passed to the function; printf
behaves as before, but this time finds another value into xmm0
).
The problem is your compiler is assuming the 20
is an int
. Your options are to either declare a float
variable and input it here OR add a typecast.
eg
printf("%f", (double)20);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.