user3220696
user3220696

Reputation:

float confusion- I'm confused how float specifier occurs

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

Answers (3)

Eric Postpischil
Eric Postpischil

Reputation: 222362

When you use the wrong specifier in printf, things such the following can happen.

The caller does this:

  • Suppose, for illustration, the stack pointer is currently at 100, and arguments are pushed onto the stack in reverse order.
  • For functions with variable argument types, float arguments are converted to double.
  • For 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.
  • For the first a, the caller changes the stack pointer to 84 and writes eight bytes to the stack.
  • For the format string, "%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.
  • It reads the pointer to the string at 80.
  • Since a pointer is four bytes, printf updates its argument pointer to point to 84.
  • The string says the next argument is %d, so printf expects a four-byte integer, and it reads four bytes from 84.
  • Since an int is four bytes, printf updates its argument pointer to point to 88.
  • Since the eight bytes at 84 to 91 contain the encoding of a 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.
  • The string says the next argument is %f, so printf expects an eight-byte double, and it reads eight bytes from 88.
  • The bytes from 88 to 95 contain four bytes from the end of the first 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

Filipe Gonçalves
Filipe Gonçalves

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

haccks
haccks

Reputation: 106012

Using a wrong conversion specifier for a data type invokes undefined behavior. You may get anything, either expected or unexpected result.

C11: 7.21.6 Formatted input/output functions:

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

Related Questions