How is conversion of float/double to int handled in printf?

The printf function uses the format specifiers to figure out what to pop off the stack. So when it sees %d, it pops off 4 bytes and interprets them as an int, which is wrong (the binary representation of (float)3.0 is not the same as (int)3).

You’ll need to either use the %f format specifiers or cast the arguments to int. If you’re using a new enough version of gcc, then turning on stronger warnings catches this sort of error:

$ gcc -Wall -Werror test.c
cc1: warnings being treated as errors
test.c: In function ‘main’:
test.c:10: error: implicit declaration of function ‘printf’
test.c:10: error: incompatible implicit declaration of built-in function ‘printf’
test.c:10: error: format ‘%d’ expects type ‘int’, but argument 4 has type ‘double’
test.c:10: error: format ‘%d’ expects type ‘int’, but argument 5 has type ‘double’

Response to the edited part of the question:

C’s integer promotion rules say that all types smaller than int get promoted to int when passed as a vararg. So in your case, the 'd' is getting promoted to an int, then printf is popping off an int and casting to a char. The best reference I could find for this behavior was this blog entry.

Leave a Comment