D
Daniel W
Hi!
I tried to post this to comp.lang.c.moderated but it didn't
seem to go through.
I've got a question about volatiles in assignment expressions.
I found the following code snippet in an embedded development
forum:
----
volatile char a;
...
if (++a == 1)
{
...
----
This code snippet was then followed by the output from two
compilers, one which was gcc. Gcc's code looked like something
like this (in RTL like form where Rn denotes a register):
R1 <- *a
R1 <- R1 + 1
*a <- R1
R2 <- *a
IF R2 == 1
Now to my question! The code above contains two read accesses
and one write access to a. I would have assumed that only one
read access should be performed. Does the standard allow the
second read operation?
I am adding a lot of standard texts that I've used when trying
to deduce the answer. Please help if you can!
Sorry for the long posting!
Regards
/Daniel W
P.s. Remove underscores from e-mail address if replying via
e-mail!
------------------------------------------------------------
Reading from the standard ISO/IEC [9899:1999] I find the
following passages related to this issue (A denotes the
rationale and B denotes the standard):
B.5.1.2.3 - 2 "Accessing a volatile object, modifying an object,
modifying a file, or calling a function that does any of those
operations are all side effects, which are changes in the state
of the execution environment. Evaluation of an expression may
produce side effects. At certain specified points in the execution
sequence called sequence points, all side effects of previous
evaluations shall be complete and no side effects of subsequent
evaluations shall have taken place." ...
B.6.5.16 - 3 "An assignment operator stores a value in the
object designated by the left operand. An assignment expression
has the value of the left operand after the assignment, but is
not an lvalue. The type of an assignment expression is the type
of the left operand unless the left operand has qualified type,
in which case it is the unqualified version of the type of the
left operand. The side effect of updating the stored value of
the left operand shall occur between the previous and the next
sequence point."
B.6.5.16.2 - 3 "A compound assignment of the form E1 op= E2
differs from the simple assignment expression E1 = E1 op E2 only
in that the lvalue E1 is evaluated only once."
B.6.3.2.1 - 2 "Except when it is the operand of the sizeof operator,
the unary & operator, the ++ operator, the -- operator, or the left
operand of the . operator or an assignment operator, an lvalue that
does not have array type is converted to the value stored in the
designated object (and is no longer an lvalue). If the lvalue have
qualified type, the value has the unqualified version of the type
of the lvalue; otherwise, the value has the type of the lvalue. If
the lvalue has an incomplete type and does not have array type, the
behavior is undefined."
B.6.5.3.1 - 2 "The value of the operand of the prefix ++ operator
is incremented. The result is the new value of the operand after
incrementation. The expression ++E is equivalent to (E+=1). See
discussions of additive operators and compound assignment for
information on constraints, types, side effects, and conversions
and the effects of operations on pointers."
B.6.7.3 - 3 "The properties associated with qualified types are
meaningfull only for expressions that are lvalues."
B.6.7.3 - 6 "An object that has volatile-qualified type may be
modified in ways unknown to the implementation or have other
unknown side effects. Therefore any expression refering to such
an object shall be evaulated strictly according to the rules of
the abstract machine, as described in 5.1.2.3. Furthermore, at
every sequence point the value stored in the object shall agree
with that prescribed by the abstract machine, except as modified
by the unknown factors mentioned previously. What constitutes
an access to an object that has volatile-qualified type is
implementetion-defined."
Annex C in the standard places a sequnce point after the controlling
expression of a selection statement.
A.6.5.2.4 "The C89 Committee did not endorse the practice in some
implementations of considering post-increment and post-decrement
operator expressions to be lvalues."
A.6.5.3.1 "See 6.5.2.4."
A.6.5.16 "The optimization rules for factoring out assignments can
also be stated. Let X(i,S) be an expression which contains no
impure functions or sequenced operators, and suppose that X
contains a storage S(i) to i which sets i to Snew(i) and returns
Sval(i). The possible expressions are
S(i): Sval(i): Snew(i):
++i i+1 i+1
i++ i i+1
--i i-1 i-1
i-- i i-1
y y y
i op= y i op y i op y
Then X(i,S) can be replaced by either
(T = i, i = Snew(i), X(T,Sval))
or
(T = X(i,Sval), i = Snew(i), T)
provided that neither i nor y have side effects themselves."
I tried to post this to comp.lang.c.moderated but it didn't
seem to go through.
I've got a question about volatiles in assignment expressions.
I found the following code snippet in an embedded development
forum:
----
volatile char a;
...
if (++a == 1)
{
...
----
This code snippet was then followed by the output from two
compilers, one which was gcc. Gcc's code looked like something
like this (in RTL like form where Rn denotes a register):
R1 <- *a
R1 <- R1 + 1
*a <- R1
R2 <- *a
IF R2 == 1
Now to my question! The code above contains two read accesses
and one write access to a. I would have assumed that only one
read access should be performed. Does the standard allow the
second read operation?
I am adding a lot of standard texts that I've used when trying
to deduce the answer. Please help if you can!
Sorry for the long posting!
Regards
/Daniel W
P.s. Remove underscores from e-mail address if replying via
e-mail!
------------------------------------------------------------
Reading from the standard ISO/IEC [9899:1999] I find the
following passages related to this issue (A denotes the
rationale and B denotes the standard):
B.5.1.2.3 - 2 "Accessing a volatile object, modifying an object,
modifying a file, or calling a function that does any of those
operations are all side effects, which are changes in the state
of the execution environment. Evaluation of an expression may
produce side effects. At certain specified points in the execution
sequence called sequence points, all side effects of previous
evaluations shall be complete and no side effects of subsequent
evaluations shall have taken place." ...
B.6.5.16 - 3 "An assignment operator stores a value in the
object designated by the left operand. An assignment expression
has the value of the left operand after the assignment, but is
not an lvalue. The type of an assignment expression is the type
of the left operand unless the left operand has qualified type,
in which case it is the unqualified version of the type of the
left operand. The side effect of updating the stored value of
the left operand shall occur between the previous and the next
sequence point."
B.6.5.16.2 - 3 "A compound assignment of the form E1 op= E2
differs from the simple assignment expression E1 = E1 op E2 only
in that the lvalue E1 is evaluated only once."
B.6.3.2.1 - 2 "Except when it is the operand of the sizeof operator,
the unary & operator, the ++ operator, the -- operator, or the left
operand of the . operator or an assignment operator, an lvalue that
does not have array type is converted to the value stored in the
designated object (and is no longer an lvalue). If the lvalue have
qualified type, the value has the unqualified version of the type
of the lvalue; otherwise, the value has the type of the lvalue. If
the lvalue has an incomplete type and does not have array type, the
behavior is undefined."
B.6.5.3.1 - 2 "The value of the operand of the prefix ++ operator
is incremented. The result is the new value of the operand after
incrementation. The expression ++E is equivalent to (E+=1). See
discussions of additive operators and compound assignment for
information on constraints, types, side effects, and conversions
and the effects of operations on pointers."
B.6.7.3 - 3 "The properties associated with qualified types are
meaningfull only for expressions that are lvalues."
B.6.7.3 - 6 "An object that has volatile-qualified type may be
modified in ways unknown to the implementation or have other
unknown side effects. Therefore any expression refering to such
an object shall be evaulated strictly according to the rules of
the abstract machine, as described in 5.1.2.3. Furthermore, at
every sequence point the value stored in the object shall agree
with that prescribed by the abstract machine, except as modified
by the unknown factors mentioned previously. What constitutes
an access to an object that has volatile-qualified type is
implementetion-defined."
Annex C in the standard places a sequnce point after the controlling
expression of a selection statement.
A.6.5.2.4 "The C89 Committee did not endorse the practice in some
implementations of considering post-increment and post-decrement
operator expressions to be lvalues."
A.6.5.3.1 "See 6.5.2.4."
A.6.5.16 "The optimization rules for factoring out assignments can
also be stated. Let X(i,S) be an expression which contains no
impure functions or sequenced operators, and suppose that X
contains a storage S(i) to i which sets i to Snew(i) and returns
Sval(i). The possible expressions are
S(i): Sval(i): Snew(i):
++i i+1 i+1
i++ i i+1
--i i-1 i-1
i-- i i-1
y y y
i op= y i op y i op y
Then X(i,S) can be replaced by either
(T = i, i = Snew(i), X(T,Sval))
or
(T = X(i,Sval), i = Snew(i), T)
provided that neither i nor y have side effects themselves."