Reputation:
Consider the following code snippet
float a=12.2;
printf("%f %d",a,a); //output 12.200000 Garbage value
but
printf("%d %f",a,a);//Output Garbage value Garbage Value
my question is why in the second printf, both %d and %f gives garbage value. I know it is because I have used %d first?..But can't find any proper explanation..
Upvotes: 2
Views: 100
Reputation: 222362
When you use the wrong specifier in printf
, things such the following can happen.
The caller does this:
float
arguments are converted to double
.printf("%d %f"), a, a)
, the caller first puts the last a
on the stack. The caller makes eight bytes of space by changing the stack pointer to 92, converts a
to double
, and writes eight bytes to the stack.a
, the caller changes the stack pointer to 84 and writes eight bytes to the stack."%d %f"
, the caller changes the stack pointer to 80 and writes a four-byte pointer to the stack.Then printf
does this:
printf
initializes a pointer to where the arguments start, 80.printf
updates its argument pointer to point to 84.%d
, so printf
expects a four-byte integer, and it reads four bytes from 84.int
is four bytes, printf
updates its argument pointer to point to 88.double
, the four bytes from 84 to 87 do not make any sense as an int
, and printf
prints whatever int
value the bits happen to represent.%f
, so printf
expects an eight-byte double
, and it reads eight bytes from 88.double
and four bytes fro the start of the second double
, so they do not make any sense as a double
, and printf
prints whatever value the bits happen to represent.This is not the way all C implementations work, but it is one thing that may happen when you use incorrect arguments with printf
. The C standard makes the behavior undefined because it does not control how implementations work, so they might behave as described as above, but they might instead be passing some of the arguments in registers. In the latter case, you would see different behaviors, such as printf
printing garbage for %d
because nothing had set the corresponding integer register to an appropriate value but printf
printing the correct value for %f
because it looked for it in a floating-point register, and the caller did place the value of a
in a floating-point register.
Upvotes: 2
Reputation: 21213
Because you can't know what will happen. If sizeof(float) != sizeof(int)
, you will definitely get a garbage value twice in the second case, since printf
read either too many bytes or too few bytes from the first argument, so it will screw up when reading the next argument (assuming arguments were passed on stack).
Another issue that arises is that the argument passed is being converted to double
, which usually has a different size from int
, and then printf
tries to pick an int
from something that is double
. There is a size mismatch (see comments below).
Either way, this invokes undefined behaviour, so you really can't "expect" anything meaningful to happen.
Upvotes: 1
Reputation: 106012
Using a wrong conversion specifier for a data type invokes undefined behavior. You may get anything, either expected or unexpected result.
If a conversion specification is invalid, the behavior is undefined.282) If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.
Using %d
to print the value of a
(float
) results in undefined behavior of the program.
Upvotes: 4