Increment Operators vs. Precedence
Chris Torek
torek at elf.ee.lbl.gov
Wed Mar 6 11:18:07 AEST 1991
In article <THOMSON.91Mar5173421 at zazen.macc.wisc.edu>
thomson at zazen.macc.wisc.edu (Don Thomson) writes:
>The example on the board is y = x++ ... So the dilemma is how to explain
>that precedence is not the issue here, that the order of operations is
>tied to the definition of prefix versus postfix increment operators.
Precedence is purely syntactic; order of operations is semantic.
All `precedence' does is assign some particular grouping to a set of
symbols that otherwise have none. For instance, given
x = a + b * c++;
there is no grouping, and precedence (and associativity) is a simple way
of describing how the expression is parsed.
Exclusive of precedence and associativity, all of the following are possible
parses for the sentence above:
((x = a) + (b * c))++
(x = (a + b)) * (c++)
(((x = a) + b) * c)++
x = (a + (b * (c++)))
The last one is the one we actually want, and we can obtain it by using
precedence and associativity rules:
post-increment > multiply > add > assign
In
a = b = 0;
a right-associative rule for assignment is necessary to force
a = (b = 0)
rather than
(a = b) = 0
, and in
x = a / b * c / d;
a left-associative rule is necessary to force
x = (((a / b) * c) / d)
rather than
x = ((a / (b * c)) / d)
or some such.
All of these simply give us some particular parse tree for some sentence.
It is up to us to assign semantics to each parse. The semantics for `c++'
are `get the current value of c, and eventually---by the time you reach
the next sequence point---store that value, plus 1, in c'.
So in
y = x++;
the parse tree looks like this:
=
/ \
/ \
/ \
y postfix-++
|
x
or in list notation, (= y (postfix-++ x)), but the order of operations is:
A. fetch current value of x
B. [store in y] and [add 1 to x]
In particular, in an expression like:
x = ++x;
we have a very specific parse tree, namely (= x (pre++ x)), but we may have
a nonspecific result, depending on implementation details:
A. fetch current value of x
B. [add 1 and store in x] and [add 1 to x]
If preincrement is implemented internally as:
- put an `add 1 to x' on the list of things to do
- fetch value of x and add 1
- store in x
- do the list of things to do
this expression might add 2 to x. If, on the other hand, it is
implemented as:
- fetch current value of x, add 1, store result in x, use result
- store result in x
the expression will add 1 to x. Since a compiler could even
(conceivably) `interleave' operations, it is possible that this might
act like `x += 0x101'.% This is rather unlikely, but explains why no
more than one side effect should be applied to any individual object
between sequence points.
----
% Consider a machine in which `add 1 to x' is implemented as `fetch low byte
of x, add 1, store; if result is 0, fetch high byte of x, add 1, store'
and where there are two `processing units' and some peculiar delays:
unit 1: unit 2:
------ ------
fetch low byte of x: (255) (busy with something else)
add 1: (0) fetch low byte of x: (255)
store: (low byte of x now 0) add 1: (0)
(delay) store: (low byte of x still 0)
(delay) fetch high byte of x: (17)
(delay) add 1: (18)
(delay) store: (x is now 1 larger)
fetch high byte of x: (18) (do something else)
add 1: (19)
store: (x is now 0x101 larger)
--
In-Real-Life: Chris Torek, Lawrence Berkeley Lab EE div (+1 415 486 5427)
Berkeley, CA Domain: torek at ee.lbl.gov
More information about the Comp.lang.c
mailing list