[net.lang.c] *p++ = *p results?

kevin@imagen.UUCP (Kevin L. Malloy) (03/22/86)

In the statement *p++ = *p; what will be the result?  Will p be equal
to itself or will p be equal to the next value it is pointing to?
In other words should p be incremented after it is evaluated or should
p be incremented after the assignment operation is finished?-- 
---
"If you can't trust a biker who can you trust?"

Sturgis '86

Name:	Kevin Malloy
Mail:	Imagen Corp. 2650 San Tomas Expressway, P.O. Box 58101
        Santa Clara, CA 95052-9400
AT&T:	(408) 986-9400
UUCP:	...{decvax,ucbvax}!decwrl!imagen!kevin 

ark@alice.UucP (Andrew Koenig) (03/24/86)

> In the statement *p++ = *p; what will be the result?  Will p be equal
> to itself or will p be equal to the next value it is pointing to?
> In other words should p be incremented after it is evaluated or should
> p be incremented after the assignment operation is finished?-- 

This is undefined, because the implementation is permitted to evaluate
either side of the assignment first.

gwyn@brl-smoke.ARPA (Doug Gwyn ) (03/24/86)

In article <312@imagen.UUCP> kevin@imagen.UUCP (Kevin L. Malloy) writes:
>In the statement *p++ = *p; what will be the result?  Will p be equal
>to itself or will p be equal to the next value it is pointing to?
>In other words should p be incremented after it is evaluated or should
>p be incremented after the assignment operation is finished?-- 

Obviously `p' equals itself!  I will assume you mean "does `p'
point to the next value after the one `p' initially pointed to?"

The technically correct answer is, `p' must be incremented
by the time the next "sequence point" (defined by X3J11) is
reached.  My copy of the draft standard is not at hand at the
moment, but I believe there is no sequence point until after
the assignment.  That would mean that either result is legal;
in other words, don't write code like this.

friesen@psivax.UUCP (Stanley Friesen) (03/24/86)

In article <312@imagen.UUCP> kevin@imagen.UUCP (Kevin L. Malloy) writes:
>In the statement *p++ = *p; what will be the result?  Will p be equal
>to itself or will p be equal to the next value it is pointing to?
>In other words should p be incremented after it is evaluated or should
>p be incremented after the assignment operation is finished?-- 
>---
	The answer is - either. They are both "correct" since timing
of side-effects like assignment and post-increment is implementation
defined i "C". Do not ever write code like this!
-- 

				Sarima (Stanley Friesen)

UUCP: {ttidca|ihnp4|sdcrdcf|quad1|nrcvax|bellcore|logico}!psivax!friesen
ARPA: ttidca!psivax!friesen@rand-unix.arpa

yde@necis.UUCP (David Elins ext. 220) (03/24/86)

In article <312@imagen.UUCP> kevin@imagen.UUCP (Kevin L. Malloy) writes:
>In the statement *p++ = *p; what will be the result? 

My understanding, confirmed by lint, is that this is an ambiguous
statement.  (lint said "warning: p evaluation order undefined")

The value of the expression p++ is p.
Therefore the value of the expression *p++ is "the thing pointed to by p".
The side effect of postincrement is that the contents of p are incremented
AFTER the expression is evaluated.

The real ambiguity is that C does not specify in which order the sides
of an assignment operator (or any operator) get evaluated (c.f. K&R p. 49).

If the left side is evaluated first then because of the postincrementing
side effect, the value of the right side would be the next item after
the one p pointed to before the statement was executed, and the outcome
would be that p points to the next item, and that the original item and
its successor (the next item) have identical values, the value of the
original "next item".

If the right side is evaluated first when it is all over,
p will still point to the next item but now the two items will maintain
their original values.

I tried a little test program (which produced the lint message) on both
System III and System V. The two systems, as implemented here gave
different results: system V evaluated the left side first, system III
did the right side first.

Boy, this stuff is hard to write about in a clear fashion. Maybe that
is why I am a programmer and not a writer (:-).

david

jsdy@hadron.UUCP (Joseph S. D. Yao) (03/27/86)

In article <312@imagen.UUCP> kevin@imagen.UUCP (Kevin L. Malloy) writes:
>In the statement *p++ = *p; what will be the result?

This kind of thing is specifically defined to be undefined.  Whenever
you have an incremented or decremented variable used elsewhere in the
same expression, the code may be interpreted either way.  If the same
variable is incremented (or decremented) more than once, the code may
be interpreted in any consistent way.
	i = 0;
	printf("%d %d %d %d %d %d\n", i++, i--, i++, i--, i++, i--);
-- 

	Joe Yao		hadron!jsdy@seismo.{CSS.GOV,ARPA,UUCP}

greg@utcsri.UUCP (Gregory Smith) (03/27/86)

In article <258@necis.UUCP> yde@necis.UUCP (David Elins ext. 220) writes:
>In article <312@imagen.UUCP> kevin@imagen.UUCP (Kevin L. Malloy) writes:
>>In the statement *p++ = *p; what will be the result? 

>My understanding, confirmed by lint, is that this is an ambiguous
>statement.  (lint said "warning: p evaluation order undefined")
>
...
>The real ambiguity is that C does not specify in which order the sides
>of an assignment operator (or any operator) get evaluated (c.f. K&R p. 49).
			       ^^^
The following operators have a defined order of execution:

a,b		first a, then b

a || b		eval a; if a==0 then b is evaluated

a && b		eval b; if a!=0 then b is evaluated

a ? b: c	eval a; if a!=0 then eval b else eval c.

This little point is very important, because much code depends on it.

This type of thing in particular is very common:

	if( p != NULL   &&   *p == What_I_am_looking_for )....

Evaluating *p will crash the program if p==NULL, but since the && operator
behaves the way it does, this will never happen.
-- 
"No eternal reward will forgive us now for wasting the dawn" -J. Morrison
----------------------------------------------------------------------
Greg Smith     University of Toronto       ..!decvax!utzoo!utcsri!greg

kwh@bentley.UUCP (KW Heuer) (04/01/86)

In article <2412@utcsri.UUCP> utcsri!greg (Gregory Smith) writes:
>[Some] operators have a defined order of execution:
>	if( p != NULL   &&   *p == What_I_am_looking_for )....
>Evaluating *p will crash the program if p==NULL, but since the && operator
>behaves the way it does, this will never happen.

Actually, on many machines dereferencing NULL doesn't crash the program,
it just returns an uninteresting result -- usually causing a program
crash much later, after which it's difficult to track down the bug.

On the 3b2, neither text or data space is anywhere near address zero,
page zero has no interesting contents, yet it is readable.  Apparently
this is so that programs that dereference NULL can be ported!  (I wish
they'd at least make it a loader option, so it could be turned off...)

Karl W. Z. Heuer (ihnp4!bentley!kwh), The Walking Lint