Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

with commenting the first //printf() I got the answer 0.000000 while without commenting the first printf() i got 5.000000 and 5.000000 ??

#include  <stdio.h>

int main(void)
{    
    float d;
    d=2+2*3/2;
    printf("%f
",d);//5.000000
    printf("%f",2+2*3/2);//5.000000
    return 0;
}
#include  <stdio.h>

int main(void)
{    
    float d;
    d=2+2*3/2;
    //printf("%f
",d);
    printf("%f",2+2*3/2);//0.000000
    return 0;
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
115 views
Welcome To Ask or Share your Answers For Others

1 Answer

As the other answer explained, when you try to print an int value using %f, the behavior is undefined, so anything can happen.

In a comment on that other answer, you suggested "if I'm lying to printf then in both examples it should be same", and I replied with another comment about the unpredictability of car crashes.

But now I'm going to try to answer your question, but there's a catch: you're going to have to sit through another little lecture first.

When you hear that something is formally undefined (this applies to any system, not just C programming), there's really only one sane course of action, namely: don't do that thing. Avoid it like the plague. It's poison, it's evil. It might seem to do something reasonable for a little while, but only long enough to tantalize you or get you dependent on it, and then it'll shift, leaving you derelict.

It's also not a good idea to ask why the thing is undefined, or what the expected range of behaviors might be, or why you saw one behavior one time and a different behavior another time. In general, none of these questions is answerable. Also, even if an answer is offered, some programmers (not you, I know, but some people) try to use the answer to justify retaining a piece of code containing undefined behavior that they think they can predict the behavior of. This exercise is perilous.

As compilers get more sophisticated, and as optimizations get more aggressive, the kinds of things that happen when your code contains undefined behavior get stranger and stranger. You really can't predict it, you really do have to avoid it.

But: what about your program? Why did the broken call

printf("%f
", 2+2*3/2);

print 0 when called in isolation, but 5 (seemingly the correct answer) when preceded by a different call which also printed 5?

To answer this, we need to know how values get passed to functions, and this varies from machine to machine, which is one of the factors that makes questions like this difficult-to-impossible to answer.

On a lot of machines, the first few values of type int get passed to functions in two or three registers which are reserved for integers, and the first few values of type double get passed in two or three registers which are reserved for doubles. (I know your program used a variable of type float, but when calling printf, floats always get promoted to double.)

So this makes it pretty easy to see why, on such a machine, a call like

printf("%f
", 2+2*3/2);

doesn't work. The expression 2+2*3/2 has type int, so its value gets placed into the first of those registers reserved for integers. But when printf finds %f in the format string, it says to itself "%f is for doubles, so my caller should have passed a double, so I'll grab a value from the first register reserved for doubles." But nothing got placed in the first register reserved for doubles, so the value printed is whatever happened to be there already, which might just be 0.

But (and you can probably see where this is going), if there was a preceding call which printed a floating-point 5 properly, then the value 5.0 got placed into that first register reserved for doubles, so when you wrongly call

printf("%f
", 2+2*3/2);

this time, printf goes to that register and finds 5, and prints it.

To test this hypothesis, I just tried an experiment. I had already determined that my machine behaved the same way yours did on your two programs, printing 5 and 5 for the first program but 0 for the second. (This was kind of a surprise, actually -- since undefined behavior means anything can happen, it's even more likely to do something different on different machines under different operating systems and different compilers.) So I tried this code:

printf("%f
", 7.7);
printf("%f
", 2+2*3/2);

See if you can guess what it printed. (And, since it seems our machines are similar, you can probably try it and get the same result on your machine, too.)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share

548k questions

547k answers

4 comments

86.3k users

...