-2

Consider these two programs:

#include <stdio.h>

int main()
{
  int z = 6.4;
  printf("%d %d", z, 6.4);
  return 0;
}

Output is 6 -1717986918.

#include <stdio.h>

int main()
{
  int z = 6.4;
  printf("%d %d", 6.4, z);
  return 0;
}

Output is -1717986918 1075419545.

Why does the output vary like that? When z was first then the output printed correct z value which was 6 as z is an integer, but when I reversed the arguments, the output is a different value. Why does it behave like that?

Suraj Jain
  • 4,463
  • 28
  • 39
  • I presume this is C, though I get the same if I compile it as C++: a language tag might get more people looking – doctorlove Jun 15 '16 at 09:11
  • I only get compiler warnings, saying that printf expects an integer while I'm feeding it a double. But it compiles and prints two sixes both times. What compiler are you using? – Janez Kuhar Jun 15 '16 at 09:15
  • @JanezKuhar Codeblocks – Suraj Jain Jun 15 '16 at 09:20
  • With gcc version 4.8.4 I get 4 sixes. However with gcc version 5.3.1 I get: 6 -1717986918 for the first `main()` and 6 6 for the second one. – Janez Kuhar Jun 15 '16 at 09:33
  • do u know why so ? – Suraj Jain Jun 15 '16 at 09:37
  • @SurajJain It is a mystery to me. – Janez Kuhar Jun 17 '16 at 09:09
  • 1
    @JanezKuhar: it is not a mystery, it is **undefined behavior**. A program with undefined behavior can produce different output on different systems and even different output on the same system when invoked multiple times. Trying to explain the observed behavior for a specific instance is hardly useful. When investigating certain situation from forensic evidence, one can come up with a useful explanation and directions for improvement. Think of plane crashes, computer virus analysis, email hacking... – chqrlie Feb 04 '17 at 16:04

1 Answers1

2

You store 6.4 in an integer which will result in z being 6. The 6 gets passed to printf which is interpreting the passed value as an decimal, thus the correct output was displayed.

But if you pass a floating point number directly to printf, and specifying the format %d, it will also interpret it as an decimal which will result in the decimal interpretations of that float.

This interpretation happens on a bit level. Float is internally stored in a rather complex format. But not like an integer. Now those bits get interpreter as an integer, and obviously the result is unreadable for humans. But the program could actually interpreted that integer as an float and reverse this action.

This site will demonstrate how floats are stored on the bit level.

And on this website you can convert the bits from the previous site to an signed integer which should output the negative number you specified in the question.

Simon Kirsten
  • 2,542
  • 18
  • 21
  • But in the second program %d is used for z still it is not outputting 6. – Suraj Jain Jun 15 '16 at 09:19
  • This happens because printf uses varargs internally and for some reason the data is corrupted because of the wrong read. Please try this line again but with `6.4f` as the parameter. I suspect this is happening because the compiler passes 6.4 as an double and thus the second `%d` is reading the second half of that double. But I might be wrong. – Simon Kirsten Jun 15 '16 at 09:24
  • 2
    passing the wrong type results in undefined behavior, period. `printf` might not even get the value from the data passed and later arguments will be in the wrong place too. Trying to elaborate on actual behavior is a moot point. – chqrlie Feb 03 '17 at 07:30
  • @SimonKirsten: `float` values are implicitly promoted to `double` when passed to vararg functions, your suggestion makes no difference, which does not means the output will be the same, since the code has undefined behavior, output might even be different for each invokation, and indeed **is** different on some architectures. – chqrlie Feb 03 '17 at 07:32
  • @chqrlie You know , you can answer that it is an UB , a beginner does not know these things, he would have happily edited his question , but you just downvote. – Suraj Jain Feb 04 '17 at 13:16
  • @SurajJain: I did not downvote at all, neither the question nor your answer. My comments were informative, your interpretation may or may not hold because ABIs differ from one environment to the other. It is essential for beginners to understand something about UB. Passing arguments inconsistent with the format string is a very good example of UB. – chqrlie Feb 04 '17 at 14:19
  • @chqrlie oh , sorry for misunderstanding , you know actually my this question is getting downvoted once in a while , and i thought you commented so you did , thanks for the upvote , can we have a chat sometime ? – Suraj Jain Feb 04 '17 at 15:20