views:

115

answers:

4

The C-faq says that the code:

int i = 7;
printf("%d\n", i++ * i++);

prints 49. Regardless of the order of evaluation, shouldn't it print 56? When I ran this code on my Turbo C 3.0 compiler it gave me the output of 56. Why is there a contradiction?

+2  A: 

Does the C-faq really say that? You're modifying a variable (i) twice with an intervening sequence point, which simply gives undefined behavior, nothing more or less. It could print 49 or 56, or 73295, or nothing at all, or "Formatting hard drive..." (and proceed to do exactly that).

Edit: As to what's likely to happen, it comes down to this: with a post-increment, the increment part can happen anywhere between the time you retrieve the value, and the next sequence point. The generated code could easily act like this:

int temp = i;
++i;
int temp2 = i;
++i;

printf("%d\n", temp * temp2);

On the other hand, it could also act like this:

int temp = i;
int temp2 = i;
++i;
++i;
printf("%d\n", temp * temp2);

While one of these two is likely, the standard doesn't mandate either one. As I said above, it's undefined behavior, which means the C standard doesn't place any limitation on what the code could do.

Jerry Coffin
No, the C-faq doesn't really say that. Questioner needs to read it more carefully.
Stephen Canon
+10  A: 

There is no contradiction. The question was worded from a user perspective, and if you carefully read the answer, you will find the remark

The behavior of code which contains multiple, ambiguous side effects has always been undefined.

So it might print 49, or 56. Undefined behavior is, after all, undefined. This is why there is no real contradiction. You might want to brush up your understanding of what are called sequence points.

Jim Brissom
Many a times such questions comes in the examinations that what will be the output of the above program,should I write there that it would be UB?
fahad
@fahad: that's up to you and your professor. "Undefined behavior" is **a** correct answer, but they may be looking for more insight into your thought process.
Michael Petrotta
@fahad: If such things come up in your exams, you are being taught by people who don't have much knowledge of C. Try to pass the exams, disregard anything your instructors say that doesn't sound right (it may well be wrong), and get your knowledge from reputable sources, like good books or Stack Overflow high-rated answers.
David Thornley
Thanks a lot...
fahad
+3  A: 

Because it's undefined behavior. The compiler can do whatever it wants: it can make the code print 56, 49, or "your mom", and the compiler would still be standards-conforming.

You can't modify the same value more than once between two sequence points.

Adam Rosenfield
+3  A: 

The expression i++ * i++ invokes undefined behavior, so any result is possible.

Why is it undefined? Because the language standard says so:

6.5 Expressions
...
2  Between the previous and next sequence point an object shall have its 
   stored value modified at most once by the evaluation of an expression.72) 
   Furthermore, the prior value shall be read only to determine the value 
   to be stored.73)
...
73) This paragraph renders undefined statement expressions such as

    i = ++i + 1;
    a[i++] = i;

while allowing

    i = i + 1;
    a[i] = i;

where "undefined behavior" means

3.4.3
1 undefined behavior
  behavior, upon use of a nonportable or erroneous program construct or of 
  erroneous data, for which this International Standard imposes no requirements

2 NOTE Possible undefined behavior ranges from ignoring the situation 
  completely with unpredictable results, to behaving during translation 
  or program execution in a documented manner characteristic of the environment 
  (with or without the issuance of a diagnostic message), to terminating a 
  translation or execution  (with the issuance of a diagnostic message).

3 EXAMPLE An example of undefined behavior is the behavior on integer overflow.

Emphasis mine.

John Bode