When I executed this code snippet:
void main(){
float a=3;
int b=5;
printf( "%d %d \n", a, b);
}
I got output as
0 1074266112
and when i changed the order of printing i.e.,
printf("%d %d \n",b,a);
I got this as output:
5 0
Why?
As your specifiers don't match the actual values, you invoke undefined behaviour. That means just anything can happen and, especially, the behaviour could change between invocations of the program (if the format specifiers read more data than actually provided) or at least between compiler settings.
What internally probably happens depends on many factors, such as the length of int values and much more. In any case, it is something you cannot rely on.
What really happens here is: float
s are automatically promoted to double
when being passed to a variadic function, changing their length to 8 bytes.
I modified your program in this way:
#include <stdio.h>
void main(){
float a=3;
int b=5;
printf("%08x %08x %08x\n", a, b);
printf("%08x %08x %08x\n", b, a);
printf("%d %d %d\n", a, b);
printf("%d %d %d\n", b, a);
}
which gives the output
00000000 40080000 00000005
00000005 00000000 40080000
0 1074266112 5
5 0 1074266112
So we exactly see the values resp. bytes being passed via the stack to printf()
. As these values are swapped due to the endianness (they are visually swapped when interpreted via %08x
), I really have the bytes
00 00 00 00 00 00 08 40 05 00 00 00
05 00 00 00 00 00 00 00 00 00 08 40
If we now use the wrong specifiers, we get the mapping
00 00 00 00 -> 00000000 -> 0
00 00 08 40 -> 40080000 -> 1074266112
05 00 00 00 -> 00000005 -> 5
which is then output.
If I omit one %d
, the respectively last value is omitted as well, leading to
0 1074266112
5 0
in turn.
So the reason why your b
value seems to change is that in the first case, you really get the "other" part of your a
value.
You code does technically invoke undefined behaviour; still there is clear logic behind the two outputs.
It has to do with variadic function and automatic type promotions.
Everytime you pass a float to a variadic function it gets automatically promoted to double. The printf specifier %f
is always interpreted as %lf
. you can try this yourself, output is always double.
First example:
float a=3;
int b=5;
printf( "%d %d \n", a, b);
( int type takes 4 bytes on you system )
You pass a float which gets promoted to a double and takes 8 bytes of stack, and a integer which takes 4 bytes. Then you try to print the first 8 bytes on the stack( with %d of 4 bytes twice ) and you get the first 4 and last 4 bytes of the ( now )double. The integer in not read.
Second example:
printf( "%d %d \n", a, b);
This is different as you first pass the integer which gets printed correctly and then you only print the first 4 bytes of the double.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With