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.