1. ## Trick Question

Do these loops do the same thing, and if so, what do they do?:
Code:
```/* assuming |str| >= 1 */
/*1*/ char *p = str; while( (*p = *++p) != '\0' ) ;
/*2*/ char *p = str; while( (*p = *(p++ + 1)) != '\0' ) ;
/*3*/ int i = 0; while( (str[i] = str[++i]) != '\0' ) ;
/*4*/ int i; for( i = 0; str[i] != '\0'; str[i] = str[++i] ) ;```
Maybe it's incredibly obvious, and maybe I should stop programming at 4 in the morning...

2. All these versions are based on undefined behaviour and could do anything.

Why do some people think x = ++y + y++ is bad? (A C++ link but applies to C too.)

3. I think they all do the same thing, i.e., they do something that results in undefined behaviour.

4. Originally Posted by anon
All these versions are based on undefined behaviour and could do anything.

Why do some people think x = ++y + y++ is bad? (A C++ link but applies to C too.)
Are you sure it's undefined?
I only see one pre or post increment per statement.

5. Originally Posted by cpjust
I only see one pre or post increment per statement.
But you also see another occurrence of the variable involved in the increment, hence the variable is read twice and yet modified between two sequence points.

6. Originally Posted by laserlight
But you also see another occurrence of the variable involved in the increment, hence the variable is read twice and yet modified between two sequence points.
Oh, duh! Of course... Now I see it.
(*p = *++p) is doing a pre-increment, so it's undefined behavior (although I would read it the same as: ++p; *p = *p )

(*p = *(p++ + 1))
Would that still be undefined behavior?
I think it's pretty clear that it's saying: *p = *(p + 1); ++p;

7. Originally Posted by cpjust
(*p = *(p++ + 1))
Would that still be undefined behavior?
Yes, presumably because the post-increment takes effect before the next sequence point. In fact, one of the examples of undefined behaviour provided by the C standard is:
Code:
`a[i++] = i;`

8. But it could be:
Code:
`*p = {*(p + 1), ++p};`
where the braced expression is computed before *p = is stored. This would be the case on a PDP-11 (or VAX, 68K) architecture, where you would get this:
Code:
```mov p, r0
mov 1(r0)+, r1
mov r1, (r0)```
[I'm not 100% sure that is actually VALID PDP-11 code, but you can probably see the intent, and whilst THIS particular case may not be valid code, it would be fairly complicated to describe the exact cases which ALL compilers CAN generate valid code for, and the list of expressions which are NOT possible to generate valid code for with such optimization enabled - it is much simpler to state "if you modify the variable in an expression, it must not be used elsewhere too"].

--
Mats

9. Originally Posted by laserlight
Yes, presumably because the post-increment takes effect before the next sequence point. In fact, one of the examples of undefined behaviour provided by the C standard is:
Code:
`a[i++] = i;`
I'm just having a hard time understanding why (other than because the standard say so) that example would be undefined, since the post-increment happens after the statement is finished...

10. Originally Posted by cpjust
I'm just having a hard time understanding why (other than because the standard say so) that example would be undefined, since the post-increment happens after the statement is finished...
Again, in 68k, you could implement that as something like this (this is NOT valid 68K assembler, but it shows the OPPURTUNITY for this to be done this way, and there is nothing saying there isn't a version of processor somewhere that supports this sort of thing)
Code:
```   lea r1, a(r0)+
mov r0, (r1)```
--
Mats

11. Originally Posted by cpjust
I'm just having a hard time understanding why (other than because the standard say so) that example would be undefined, since the post-increment happens after the statement is finished...
Maybe we can reason this way:
Code:
`a[i++] = x;`
is effectively equivalent to:
Code:
```T temp = i++;
a[temp] = x;```
Therefore:
Code:
`a[i++] = i;`
can be written as:
Code:
```T temp = i++;
a[temp] = i;```
You can disagree, but the compiler can point out that by the language rules i will not be read second time before the next sequence point, so surely the transformation is correct.

12. Originally Posted by laserlight
Maybe we can reason this way:
Code:
`a[i++] = x;`
is effectively equivalent to:
Code:
```T temp = i++;
a[temp] = x;```
Therefore:
Code:
`a[i++] = i;`
can be written as:
Code:
```T temp = i++;
a[temp] = i;```
You can disagree, but the compiler can point out that by the language rules i will not be read second time before the next sequence point, so surely the transformation is correct.
But doesn't that defeat the whole point of the post-increment? Otherwise it's not doing the "post" part of the increment.

13. Originally Posted by cpjust
But doesn't that defeat the whole point of the post-increment? Otherwise it's not doing the "post" part of the increment.
It is POST getting the value of i for the index - which is what the standard says anything about - it does specifically say that "it will happen before the next sequence point", but nothing about where within the sequence point it is actually being done. As I have tried to show in the small snippets of 68K/PDP-11 (or similar), it is POSSIBLE to have ONE instruction that does fetch and increment at the same time.

--
Mats

14. Originally Posted by matsp
As I have tried to show in the small snippets of 68K/PDP-11 (or similar), it is POSSIBLE to have ONE instruction that does fetch and increment at the same time.
Ah, so that's what that does... I'm not very Assembly literate.

15. Thanks for clearing that up all. I'm going to need to re-read this a couple times to fully understand why the post-increment results in undefined behaviour.