简体   繁体   中英

Why does an integer interpreted as a double render zero?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM