1

Example code

int arr[3] = { 0, 1 };
int* buf = arr;
*buf++ = *buf + 10;

Result of last expression is that buf[0] == 10. I taught it would be buf[0] == 11.

A college of mine wrote something similar to the example code and I taught it works differently than it does. And I would like to know why it works the way it does.

The way I went about figuring it out was to look at the operator precedence table. There it states that suffix ++ has precedence over dereference. Hence I taught that on the left of operator= buf would point to the first element, but on the right of the operator= it would have already been incremented and would point to the second element. However that is not the case.

My question is, why is that so? Preferably a standard quote :) However any explanation is welcome!

rozina
  • 4,120
  • 27
  • 49
  • 6
    Here's a standard quotation: ***undefined behavior*** *- behavior for which this International Standard imposes no requirements* – chris Feb 21 '14 at 19:09
  • 5
    I don't see why people downvote these dups, it is not clear to me that it is that easy search for this type of problem. Just vote to close. – Shafik Yaghmour Feb 21 '14 at 19:12
  • 4
    @ShafikYaghmour: Agreed. If you don't know why this behavior is undefined how could you possibly know to include the term "sequence point" in your search? – Ed S. Feb 21 '14 at 19:13
  • Wow, where did the great possible duplicate link go? I think that will help me (I am still reading it). I read a similar question on SO but I still didn't have an answer to my question. – rozina Feb 21 '14 at 19:14
  • If you refresh the page it should be at the top now. The *C* version of this is [Why are these constructs undefined behavior?](http://stackoverflow.com/questions/949433/why-are-these-constructs-undefined-behavior) – Shafik Yaghmour Feb 21 '14 at 19:15
  • Yea I read the C version, and that was not enough for me :) – rozina Feb 21 '14 at 19:18
  • @rozina: It moves to the top when the duplicate is confirmed. – Lightness Races in Orbit Feb 21 '14 at 19:22
  • @LightnessRacesinOrbit Ah thank you. Although after reading the whole post I still don't understand. Or maybe I do. Is dereferencing a variable considered accessing it? In that case it is clear to me :) – rozina Feb 21 '14 at 19:24
  • @rozina: Yes, reading (dereferencing) is access. – Ed S. Feb 21 '14 at 19:30
  • @rozina: At a broad level, yes. That's not the definition of the word in C++, though, so don't go around using that terminology for this! – Lightness Races in Orbit Feb 21 '14 at 19:31
  • @LightnessRacesinOrbit So if that is not a definition in C++ how come it falls into the standard saying it is undefined behaviour? – rozina Feb 21 '14 at 19:34
  • @rozina: Because that's said in different words ;P "Dereference", in C++, means taking a pointer and getting the thing it points to, which is not fundamental to what's going on with _this_ issue. (i.e. Take the pointers out of the equation and it's still Undefined Behaviour) In the broader scope of Computer Science, "dereferencing" could be said to mean reading the value of _any_ variable (which is what I suppose Ed S. was getting at, above), but that's not how we do things in C++. – Lightness Races in Orbit Feb 21 '14 at 19:38
  • @LightnessRacesinOrbit If you take the pointers out you get UB because there are two assignments happening in the same expression. I guess I still don't understand why my expression is UB :) The the duplication link doesn't give me the answer either. Or I just don't get it. I was hoping to get the answer here though :) – rozina Feb 21 '14 at 19:41
  • @rozina `++` is an assignment (of sorts), and `*` needs to do a read. Having those two things between sequence points is where the UB comes from. If you did `++` twice then that's another example because `++` needs to do a read too! – Lightness Races in Orbit Feb 21 '14 at 19:43
  • @LightnessRacesinOrbit Firstly thanks for your time! Ok I get that. In that case dereferencing (or maybe I should say dereference operator?) is accessing! I use the word access, since the standard uses that word. Ofc it makes sense that dereferencing is accessing, since as you put it, it has to read the value to dereference it. Thanks for helping me clear the confusion! I need to fully understand it in order to explain it to anyone that will ask me at work :) – rozina Feb 21 '14 at 19:48

1 Answers1

2

You are accessing and modifying the pointer multiple times in a single sequence point. This is undefined behavior.

More generally, reading from and writing to any variable between sequence points is undefined. The fact that you have a pointer in this specific example is by-the-by.

To avoid confusion with the pointer:

int i = 0;
i++ = i + 1; // UB

Logically, should the i on the right hand side be the "current" value of i, or the modified value? This is why it is undefined. Instead, separate the code:

int i = 0;
++i;
i = i + 1;

Which is clear, and well defined.

Zac Howland
  • 15,777
  • 1
  • 26
  • 42
  • I must say I didn't know that dereferencing a variable multiple times in the same expression is undefined behavior. Or is it just when you combine it with modifying it at the same time? From the links I was given I only see that modifying a variable multiple times in a single expression is undefined behaviour. – rozina Feb 21 '14 at 19:22
  • @rozina It this case, it is the combination of dereferencing and modifying. In general, it is just modifying. `*buf` on the right hand side of the equal sign is, specifically, the problem here (since it is unknown whether it should be the value prior to the pointer increment, or after). – Zac Howland Feb 21 '14 at 19:39
  • Let's not call it "dereferencing", alright? In C++ that means something very specific, which is not fundamental to this issue, and it's caused the OP some confusion. You're also a bit confused about what a sequence point is - they can neither be "dereferenced" nor modified. – Lightness Races in Orbit Feb 21 '14 at 19:40
  • I've edited this answer more radically than I usually would, in order to address some confusion that the OP is alarmingly swiftly developing, and since this question is closed anyway. Forgive me :) – Lightness Races in Orbit Feb 21 '14 at 19:42
  • @LightnessRacesinOrbit True, the wording was a bit misleading. – Zac Howland Feb 21 '14 at 19:43
  • @LightnessRacesinOrbit One more question about the example you have put in your answer. Would anything change if `int i` was a custom type (a class that would have operator++ defined)? Because the way I look at operators is as if they are just like any other function. – rozina Feb 21 '14 at 19:50
  • @rozina - If you defined `operator++` to do something that isn't consistent with convention (shame on you for that, by the way!), then all bets are off. The key to this problem is that you cannot modify a variable (of any type) multiple times in a single sequence point. – Zac Howland Feb 21 '14 at 19:52
  • The problem with my understanding is, that a function call seems to be a sequence point. So once you enter the body of operator++ the previous sequence point is over. Or am I missing something? - Never mind, I found the information in the duplicate link. It is a function call but there is no sequence point between the call and the expression in which the operator is in. – rozina Feb 21 '14 at 19:54
  • @rozina For built-in types, it is not a function. If you define a custom type that implements `operator++` that modifies the type, there is no guarantee that function will run before another. For example, `t++ = t + 1` - since you cannot guarantee that `t++` will run prior to `t + 1` they are part of the same sequence point. – Zac Howland Feb 21 '14 at 19:58
  • @rozina: If you still don't quite get it, this is probably a more elegant explanation: `Sequence point is a point in time at which the dust has settled and all side effects which have been seen so far are guaranteed to be complete.` ([Source](http://stackoverflow.com/a/4176333/529761)) – Zac Howland Feb 21 '14 at 20:03
  • Thanks man. I think I am close, but not quite there yet. But I will try to get there with the help of google to answer my side questions :) Thanks for all the help! – rozina Feb 21 '14 at 20:09