3

*(p1++)

int array[10] = {1,2};
int *p1 = array;
*p1=24;
*p1= *(p1++);
for (int i : array)
    cout << i << " ";

Output is 24 24

*(++p1)

int array[10] = {1,2};
int *p1 = array;
*p1=24;
*p1= *(++p1);
for (int i : array)
    cout << i << " ";

Output is 24 2

It seems like this is the exact opposite of doing increment with values. Can someone explain what is going on here? Thanks!

Patrick Duncan
  • 549
  • 1
  • 6
  • 17
  • 4
    Just more fun examples of **undefined behavior** is not always what you expect. – JSF Dec 10 '15 at 01:01
  • Yup- codepad reports both the pre and post index as undefined. Think about why for a bit. – Michael Dorgan Dec 10 '15 at 01:02
  • **IF** the compiler is friendlier than it needs to be toward undefined behavior, the first examples reads the 24 and stores it either back where it read it or where the 2 was. The second reads the 2 and stores it either where the 24 was or back where the 2 was. Expecting anything about which of those two destinations is chosen for each is absurd. Even expecting there are only those two choices is unsound. – JSF Dec 10 '15 at 01:09
  • Are you sure you don't have the outputs backwards from those two examples? – J. Murray Dec 10 '15 at 01:12
  • [Cpp.sh link](http://cpp.sh/24gly) Okay, looks like it is an undefined behaviour. Odd question for an exam. Edit: The output is correct – Patrick Duncan Dec 10 '15 at 01:12
  • I'm surprised no one quoted the standard yet on the general kind of undefined behavior this is. But to understand why it must be UB, think about what rule tells you when the left hand side address is computed. We can reasonably infer the store to that address is after the read of the value to be stored, but the computation of that address could be anywhere from the first thing the line does to the second to last thing: Certainly it can be either before or after `p1` is changed. – JSF Dec 10 '15 at 01:16
  • @JSF Which standard would we quote? No specific version of C++ was specified in the question. – David Schwartz Dec 10 '15 at 01:18
  • It was UB behavior before any C++0x existed and I'm sure it is still UB in C++17 and back when C++ was so new the standard didn't tell you it was UB, it was still UB and the standard just wasn't complete enough to tell you. This is not version specific. – JSF Dec 10 '15 at 01:21
  • `You've earned the "Disciplined" badge (Delete own post with score of 3 or higher) for "Pre/Post Increment Pointers in C++".` -- well, that's some consolation. – Mike Nakis Dec 10 '15 at 01:38
  • Possible duplicate of [Undefined behavior and sequence points](http://stackoverflow.com/questions/4176328/undefined-behavior-and-sequence-points) –  Dec 10 '15 at 02:04
  • @MikeNakis it goes to show that people upvote posts for being formatted nicely, rather than the actual post content..:) – M.M Dec 10 '15 at 02:04
  • @M.M meh, possibly. But I would prefer to believe that the upvotes were due to the fact that I sounded very convincing. C-:= – Mike Nakis Dec 10 '15 at 02:07

3 Answers3

2

There is an undefined behavior in

*p1 = *(p1++);

because, quoting §1.9/15:

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

Side effect here is an increment of p1 and value computation is a computation of address using p1.

So you shouldn't rely on the exact outcome of your examples.

vitaut
  • 49,672
  • 25
  • 199
  • 336
1
*p1= *(p1++);

This just doesn't make sense. The semantic meaning of this operation is different depending on which side of the = is evaluated first. So there's no way you can make any sense out of it.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
-1

For *(p1++):

*p1 = *(p1++)

p1++ will increment p1 to point to index 1 in the array, and return the previous value of p1 (index 0). So *(p1++) will return 24, and *p1 will now equal 2. *p1 is then assigned that return value (24), so the array will be {24,24}.

for *(++p1):

*p1 = *(++p1)

++p1 will increment p1 to point to index 2 in the array, and return the current value of p1 (index 1). So *(++p1) will return 2, and *p1 will now equal 2. *p1 is then assigned that return value (2), which is the original value at the index of p1 (1), so the array will remain {24,2}

Iinferno1
  • 49
  • 1
  • 6