-2

Let's say I have the following code:

int i = 0;
func(i++, i++);

The increment is happening right after returning the value? Is it guaranteed that the first argument will be 0, and the second argument will be 1?

iTayb
  • 12,373
  • 24
  • 81
  • 135
  • 2
    Why is garbage code continually posted on SO with requests to explain why it's garbage? Is it so difficult to avoid code like this that questions have to be asked about it? FFS stop writing crap and then asking about it. – Martin James Jun 23 '15 at 11:55
  • @MartinJames What's so wrong with trying to understand why it fails? – iTayb Jun 23 '15 at 13:12
  • @MartinJames: Because new learners don't understand what is and isn't garbage yet. It's our job to teach them, carefully and patiently. Did you once have misunderstandings about how C works? If so, you can't blame someone else for having the same misunderstandings at first. – Steve Summit Jun 23 '15 at 13:59
  • @iTayb: As you can see from the answers and comments so far, code like you have posted can be very confusing. It is very hard to figure out what the code should do. In fact, the compilers can't figure it out, either -- different compilers will give different answers, and none of them is wrong. This particular code fragment is both unspecified and undefined. If you want it to have well-defined behavior, you have to introduce some sequence points, perhaps by writing `int first = i++; int second = i++; func(first, second);`. – Steve Summit Jun 23 '15 at 14:01
  • @SteveSummit - no, it's not. Profs and TA's teach. SO contributors answer questions from professional and enthusiast programmers. If there is doubt about code such as supplied by the OP, the OP should have simplified it, perhaps using some intermediate temp vars, and tested/debugged before posting on SO:( – Martin James Jun 23 '15 at 14:14
  • @iTayb it's not. What is wrong is posting such code on a Q&A site for professional and enthusiast programmers. Such programmers would be fired or get the lowest fail grade possible for issuing such code, code that is easily avoidable by incing the vars either before, or after, the function call, so removing the FUD. – Martin James Jun 23 '15 at 14:20
  • @MartinJames: The code in question is already simplified about as far as it can be! And if you don't want to teach or explain, the straightforward answers to the OP's questions are simply "no" and "no". – Steve Summit Jun 23 '15 at 14:32
  • @SteveSummit no, it's just not simple. 'int i = 0; int j = i+1; func(i,j);' is simple. – Martin James Jun 23 '15 at 16:31
  • Anyway. @iTayb: It's a fair question, and I'm glad you asked it and that you got good answers, and that you didn't just test the code yourself, and perhaps learn a false lesson about what the code does based on how your compiler happens to handle it today. – Steve Summit Jun 23 '15 at 16:54

4 Answers4

7

This code is broken for two reasons:

  • Accessing a variable twice between sequence points, for other purposes than to determine which value to store, is undefined behavior. There are no sequence points between the evaluation of function parameters. Meaning anything could happen, your program might crash & burn (or more likely display incorrect or garbage values).
  • The order of evaluation of function parameters is unspecified behavior, meaning you can't know which one that will be evaluated first.

Undefined behavior and sequence points

Why are these constructs (using ++) undefined behavior?

Community
  • 1
  • 1
Lundin
  • 195,001
  • 40
  • 254
  • 396
  • The unspecified behavior will not "break" the code by itself. If the function can handle the result the behavior stays defined. – this Jun 23 '15 at 11:05
1

No, your code is erroneous. There is no sequence point between the evaluation of function arguments, and two operations with side effect on the same object are only allowed if they are separated by a sequence point.

Your concept of "run instantly" doesn't exist in C. Closest comes perhaps the idea of sequenced operations, where the above mentioned sequence points forcibly separate the execution of two statements or expressions.

Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
0

Is it guaranteed that the first argument will be 0, and the second argument will be 1?

No. Its undefined behavior. The order of evaluation of function arguments are not guaranteed from left to right or right to left, i.e. order of evaluation is unspecified and therefore side effect on i is unsequenced.

C11:6.5 Expressions (p2)

If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined [...]

Community
  • 1
  • 1
haccks
  • 104,019
  • 25
  • 176
  • 264
  • 3
    Your explanation has nothing to do with the fact that this is undefined. – Jens Gustedt Jun 23 '15 at 10:58
  • 1
    Still not much better, it could be unspecific but still sequenced one way or the other. – Jens Gustedt Jun 23 '15 at 11:07
  • 1
    @JensGustedt; What do you mean by *still sequenced one way or the other*? – haccks Jun 23 '15 at 11:11
  • 1
    Even if the standard leaves the latitude to the implementation to do the evaluation in any order, it could impose that between each of these would be placed a sequence point. The standard calls this *indeterminately sequenced*. This holds e.g for initialization expressions in an initializer list. – Jens Gustedt Jun 23 '15 at 12:11
-1

When you write i++, you are asking for two things to happen:

  1. fetch the value of i and add one to it
  2. store the result back into i

Now, what you have to understand is that although #1 happens immediately, #2 does not. The right way to think about #2 is that it happens "sometime later". That's why we can't say what func(i++, i++); does. We have no way of knowing whether one of the i++'s stores its result back into i before or after the second i++ happens.

Steve Summit
  • 45,437
  • 7
  • 70
  • 103
  • 1
    No, wrong answer. There is no "sometime later", here. The compiler is even allowed to evaluate the two expressions simultaneously in parallel if the hardware permits it. – Jens Gustedt Jun 23 '15 at 10:59
  • With respect, it's not a "wrong answer", it's just a deliberately simplified one.. – Steve Summit Jun 23 '15 at 11:34
  • No it is not just simplified, it is wrong. The idea that one would happen after the other ("sometime later") gives a false impression that the store happens "after" the increment itself. Many processors have an instruction for this kind of operation, so they "happen" at exactly the same time. And then your discussion about the two different `i++` is also misleading. The code is an error because of the lack of sequence points, so the compiler could do anything that pleases, here. (BTW, the downvote is not mine.) – Jens Gustedt Jun 23 '15 at 11:59
  • @JensGustedt: We're emphasizing different aspects of the undefinedness, that's all. Yes, the store might happen immediately along with the increment -- in fact that's what the poster already thinks. But it might also happen sometime well after the increment, and it's important that the poster understand that, too. The poster wonders if he's guaranteed to get (0, 1), and he's not. He might get (0, 0). (And of course he might also get (1, 0), or perhaps a really bizarre and inexplicable result.) – Steve Summit Jun 23 '15 at 13:58