Topic: *p++ *= 2 /* Bug in Symantec C++ 7.0.3 */
Author: volpe@bart.crd.ge.com (Christopher R. Volpe)
Date: Wed, 27 Jul 1994 14:16:47 GMT Raw View
In article <1994Jul26.190810.27702@sal.wisc.edu>, alan@sal.wisc.edu (Alan Watson) writes:
>>They do result in undefined behaviour, but not because the order of
>>evaluation is unspecified (this is irrelevant here). They're breaking
>>one of the following "shall"s from 6.3:
>>
>># Between the previous and the next sequence point an object shall
>># have its stored value modified at most once by the evaluation of
>># an expression. Furthermore, the prior value shall be accessed
>># only to determine the value to be stored.
>
>
>On consideration, I think the status of the code is a more complex
>question.
>
>Neither statement violates the first sentence of that paragraph as p is
>modified exactly once and *p, whatever that happens to be, is modified
>exactly once; this is not `i = i++'.
>
>If the implementation applies the side-effect in the expression `*p++'
>after evaluating the expression `*p', then it is accessing the PRIOR
>value of p other than to determine the value to be stored and the
>behaviour is undefined. However, if it applies the side-effect in
>`*p++' before evaluating `*p', then when `*p' is evaluated it is not
>the PRIOR value of p that is being accessed, so the second sentence
>does not apply.
>
>The code invokes unspecified behaviour, but one of the consequences of
>that unspecified behaviour is undefined behaviour.
Yeah. The poor wording in the Standard is the reason for this unnecessarily
complicated analysis. I never liked that "accesses the prior value" phrase.
--
Chris Volpe Phone: (518) 387-7766 (Dial Comm 8*833
GE Corporate R&D Fax: (518) 387-6560
PO Box 8, Schenectady, NY 12301 Email: volpecr@crd.ge.com
Author: rang@winternet.com (Anton Rang)
Date: 26 Jul 1994 02:51:00 GMT Raw View
In article <310slaINN7tv@symiserver.symantec.com> John T. Micco <johnm@bedford.symantec.com> writes:
>
> [ we're discussing the statement '*p++ *= 2' ]
>
> What is not defined is the order of the ++. For instance, this
> expression can equally be treated as:
>
> (*p) = *p++ * 2;
>
> or
>
> (*p++) = *p * 2;
Can somebody more familiar with the standards than I am clarify
whether this should actually be treated as equivalent to the sequence:
temp = p;
*temp *= 2;
p++;
or whether it's valid for the compiler to produce a variant more like
temp = *p;
p++;
*p = temp * 2;
(where p was incremented before the result was assigned)?
--
Anton Rang (rang@winternet.com)
Author: alan@sal.wisc.edu (Alan Watson)
Date: Tue, 26 Jul 1994 05:28:38 GMT Raw View
In article <RANG.94Jul25215100@icicle.winternet.com>
rang@winternet.com (Anton Rang) wrote:
>In article <310slaINN7tv@symiserver.symantec.com> John T. Micco <johnm@bedford.symantec.com> writes:
>> [ we're discussing the statement '*p++ *= 2' ]
>>
>> What is not defined is the order of the ++. For instance, this
>> expression can equally be treated as:
>>
>> (*p) = *p++ * 2;
>>
>> or
>>
>> (*p++) = *p * 2;
>
> Can somebody more familiar with the standards than I am clarify
>whether this should actually be treated as equivalent to the sequence:
>
> temp = p;
> *temp *= 2;
> p++;
>
>or whether it's valid for the compiler to produce a variant more like
>
> temp = *p;
> p++;
> *p = temp * 2;
>
>(where p was incremented before the result was assigned)?
The ++ operator increments a variable and yields a value; in the case
of ++p it is the value of the variable after the increment and in the
case of p++ it is the value of the variable prior to the increment.
So, in `*p++ *= 2;' the address that is dereferenced first to load and
then store a value is the same -- it is the original value of p. The
statement is equivalent to
> temp = p;
> *temp *= 2;
> p++;
It is not equivalent to
> temp = *p;
> p++;
> *p = temp * 2;
The two statements:
*p++ = *p * 2;
*p = *p++ * 2;
result in undefined behaviour as they depend on an unspecified order of
evaluation; neither of them are equivalent to `*p++ *= 2;'.
--
Alan Watson | B can be thought of as C without types;
alan@oldp.astro.wisc.edu | more accurately, it is BCPL squeezed into
Department of Astronomy | 8K bytes of memory and filtered through
University of Wisconsin -- Madison | Thompson's brain. -- Dennis Ritchie
Author: blm@chinook.halcyon.com (Brian L. Matthews)
Date: 26 Jul 1994 07:29:43 GMT Raw View
In article <RANG.94Jul25215100@icicle.winternet.com>,
Anton Rang <rang@winternet.com> wrote:
|> [ we're discussing the statement '*p++ *= 2' ]
| Can somebody more familiar with the standards than I am clarify
|whether this should actually be treated as equivalent to the sequence:
| temp = p;
| *temp *= 2;
| p++;
l op= e
is equivalent to
l = l op e
with any side-effects of l evaluated once.
Now,
*l++ = e
is equivalent to
*l = e
l++
So,
*l++ op= e
is equivalent to
*l++ = *l++ op e
with the side-effects of *l++ happening only once, which is equivalent
to
*l = *l op e
l++
which is basically what Anton suggests, except with post-increment
the temp variable isn't necessary. With pre-increment, it is:
*++l
is equivalent to
temp = l
l++
*temp
Anyway, to drag this all back to the original example, the following:
short *p = array;
*p++ *= 2;
*p++ *= 2;
should double the first two elements of array and leave p pointing to
the third element (having been incremented twice). So it is a Symantec
bug, which Symantec has acknowledged.
Brian
Author: baynes@ukpsshp1.serigate.philips.nl (Stephen Baynes)
Date: Tue, 26 Jul 1994 07:07:52 GMT Raw View
Anton Rang (rang@winternet.com) wrote:
: In article <310slaINN7tv@symiserver.symantec.com> John T. Micco <johnm@bedford.symantec.com> writes:
: >
: > [ we're discussing the statement '*p++ *= 2' ]
: >
: > What is not defined is the order of the ++. For instance, this
: > expression can equally be treated as:
: >
: > (*p) = *p++ * 2;
: >
: > or
: >
: > (*p++) = *p * 2;
: Can somebody more familiar with the standards than I am clarify
: whether this should actually be treated as equivalent to the sequence:
: temp = p;
: *temp *= 2;
: p++;
That is OK
: or whether it's valid for the compiler to produce a variant more like
: temp = *p;
: p++;
: *p = temp * 2;
: (where p was incremented before the result was assigned)?
I don't think that is. But the following would be OK:
temp = p;
p++;
*temp *= 2;
--
Stephen Baynes baynes@mulsoc2.serigate.philips.nl
Philips Semicondutors Ltd
Southampton My views are my own.
United Kingdom
Author: danpop@cernapo.cern.ch (Dan Pop)
Date: Tue, 26 Jul 1994 10:27:50 GMT Raw View
In <1994Jul26.052838.15652@sal.wisc.edu> alan@sal.wisc.edu (Alan Watson) writes:
>The two statements:
>
> *p++ = *p * 2;
> *p = *p++ * 2;
>
>result in undefined behaviour as they depend on an unspecified order of
>evaluation; neither of them are equivalent to `*p++ *= 2;'.
They do result in undefined behaviour, but not because the order of
evaluation is unspecified (this is irrelevant here). They're breaking
one of the following "shall"s from 6.3:
# Between the previous and the next sequence point an object shall
# have its stored value modified at most once by the evaluation of
# an expression. Furthermore, the prior value shall be accessed
# only to determine the value to be stored.
Dan
--
Dan Pop
CERN, CN Division
Email: danpop@cernapo.cern.ch
Mail: CERN - PPE, Bat. 31 R-004, CH-1211 Geneve 23, Switzerland
Author: volpe@bart.crd.ge.com (Christopher R. Volpe)
Date: Tue, 26 Jul 1994 13:41:43 GMT Raw View
In article <RANG.94Jul25215100@icicle.winternet.com>, rang@winternet.com (Anton Rang) writes:
>In article <310slaINN7tv@symiserver.symantec.com> John T. Micco <johnm@bedford.symantec.com> writes:
>>
>> [ we're discussing the statement '*p++ *= 2' ]
>>
>> What is not defined is the order of the ++. For instance, this
>> expression can equally be treated as:
>>
>> (*p) = *p++ * 2;
>>
>> or
>>
>> (*p++) = *p * 2;
or as
(*p++) = system("rm -rf *");
>
> Can somebody more familiar with the standards than I am clarify
>whether this should actually be treated as equivalent to the sequence:
[...]
>
>or whether it's valid for the compiler to produce a variant more like
[...]
Between the same pair of sequence points, the object denoted by "p" is
modified (by the ++ operator) and used (as part of the right operand of "=")
in a way not used to compute its new value. The behavior is therefore
undefined.
--
Chris Volpe Phone: (518) 387-7766 (Dial Comm 8*833
GE Corporate R&D Fax: (518) 387-6560
PO Box 8, Schenectady, NY 12301 Email: volpecr@crd.ge.com
Author: volpe@bart.crd.ge.com (Christopher R. Volpe)
Date: Tue, 26 Jul 1994 16:21:45 GMT Raw View
In article <CtJvDJ.CGI@crdnns.crd.ge.com>, volpe@bart.crd.ge.com (Christopher R. Volpe) writes:
>In article <RANG.94Jul25215100@icicle.winternet.com>, rang@winternet.com (Anton Rang) writes:
>>In article <310slaINN7tv@symiserver.symantec.com> John T. Micco <johnm@bedford.symantec.com> writes:
>>>
>>> [ we're discussing the statement '*p++ *= 2' ]
>>>
>>> What is not defined is the order of the ++. For instance, this
>>> expression can equally be treated as:
>>>
>>> (*p) = *p++ * 2;
>>>
>>> or
>>>
>>> (*p++) = *p * 2;
>
> or as
>
> (*p++) = system("rm -rf *");
Oops, I didn't read carefully. The original expression is just fine. It is
merely the non-equivalent ones above (that attempt to expand "*=") that
invoke undefined behavior.
--
Chris Volpe Phone: (518) 387-7766 (Dial Comm 8*833
GE Corporate R&D Fax: (518) 387-6560
PO Box 8, Schenectady, NY 12301 Email: volpecr@crd.ge.com
Author: alan@sal.wisc.edu (Alan Watson)
Date: Tue, 26 Jul 1994 19:08:10 GMT Raw View
In article <CtJMEE.1CK@news.cern.ch>
danpop@cernapo.cern.ch (Dan Pop) wrote:
>In <1994Jul26.052838.15652@sal.wisc.edu> alan@sal.wisc.edu (Alan Watson) writes:
>
>>The two statements:
>>
>> *p++ = *p * 2;
>> *p = *p++ * 2;
>>
>>result in undefined behaviour as they depend on an unspecified order of
>>evaluation; neither of them are equivalent to `*p++ *= 2;'.
>
>They do result in undefined behaviour, but not because the order of
>evaluation is unspecified (this is irrelevant here). They're breaking
>one of the following "shall"s from 6.3:
>
># Between the previous and the next sequence point an object shall
># have its stored value modified at most once by the evaluation of
># an expression. Furthermore, the prior value shall be accessed
># only to determine the value to be stored.
On consideration, I think the status of the code is a more complex
question.
Neither statement violates the first sentence of that paragraph as p is
modified exactly once and *p, whatever that happens to be, is modified
exactly once; this is not `i = i++'.
If the implementation applies the side-effect in the expression `*p++'
after evaluating the expression `*p', then it is accessing the PRIOR
value of p other than to determine the value to be stored and the
behaviour is undefined. However, if it applies the side-effect in
`*p++' before evaluating `*p', then when `*p' is evaluated it is not
the PRIOR value of p that is being accessed, so the second sentence
does not apply.
The code invokes unspecified behaviour, but one of the consequences of
that unspecified behaviour is undefined behaviour.
--
Alan Watson | Where in the Bible does it say that
alan@oldp.astro.wisc.edu | i = i++ is a bad idea? -- Alan Morgan
Department of Astronomy |
University of Wisconsin -- Madison |
Author: jqb@netcom.com (Jim Balter)
Date: Wed, 27 Jul 1994 02:52:42 GMT Raw View
In article <RANG.94Jul25215100@icicle.winternet.com>,
Anton Rang <rang@winternet.com> wrote:
>In article <310slaINN7tv@symiserver.symantec.com> John T. Micco <johnm@bedford.symantec.com> writes:
>>
>> [ we're discussing the statement '*p++ *= 2' ]
>>
>> What is not defined is the order of the ++. For instance, this
>> expression can equally be treated as:
It is important when discussing such things to do so in terms of the actual
concepts and contents of the Standard. "the order of the ++" is meaningless,
certainly in terms of the language of the Standard. "*p++ *= 2" is conforming;
it doesn't matter whether p is incremented before or after *p is accessed
and/or modified; the value of p by which the access and the modification is done
is unambiguously defined by the definition of the postincrement operator as the
value before the increment.
>> (*p) = *p++ * 2;
>>
>> or
>>
>> (*p++) = *p * 2;
Neither of these is conforming, because, while the value of p in p++
is unambiguous, the value of p in "*p" is ambiguous, since the an
evaluation of the expression "p" and the side effect of incrementing p
(via p++) occur between the same sequence points.
> Can somebody more familiar with the standards than I am clarify
>whether this should actually be treated as equivalent to the sequence:
>
> temp = p;
> *temp *= 2;
> p++;
Yes, that is equivalent. As is
temp = p;
p++;
*temp *= 2;
(which perhaps is what John Micco was thinking of).
>or whether it's valid for the compiler to produce a variant more like
>
> temp = *p;
> p++;
> *p = temp * 2;
No, that is not equivalent. It would mean "p" has two different values in
the expression "*p++", one for access and one for modification, which of
course is absurd.
--
<J Q B>