precedence, sequence point, side effect

S

Sensorflo

After browsing though many newsgroups articels I'm still not shure how
operator precedence, operator associativity, sequence points, side
effects go together. Currently I have the following view:

An expression
a = b() + c() * d++;

can be transformed with the rules of operator associativity and
operator precedence into a tree

-> store in d ----> store in a
| |
d -> ++ --> * --> + --> = --> ( discard )

^ ^
| |
c -> () ----- |
|
|
b -> () -----------

This tree ( and thus operator precedence and operator associativity )
define demonstrativly the order in which some operators are executed (
for example ++ is executed befor *, which is executed befor + ) but
not of all. For example the function call operators c() and b() can be
called in any order, however c() before * and b() befor +.

Side effects are any computation of an operator which is not used to
compute its result (on which other operators depend, i.e. parent nodes
in the tree). For example n++ computes the result n, but as a side
effect it stores n+1 in n. Or n=1 has the result 1, but as side effect
it stores 1 in n. As can be viewn demonstrativly in the tree, side
effects can be executed anywhere between after their operator has been
executed and the sequence point, since they have no operations
depending on them.

Now sequence points define subtrees of a tree. Before the result of
such a subtree (that is the result of the root node) can be used, all
operations (i.e. nodes) of this subtree must have been completed.

Is this view about correct?
 
B

Bob Hairgrove

After browsing though many newsgroups articels I'm still not shure how
operator precedence, operator associativity, sequence points, side
effects go together. Currently I have the following view:

An expression
a = b() + c() * d++;

can be transformed with the rules of operator associativity and
operator precedence into a tree

-> store in d ----> store in a
| |
d -> ++ --> * --> + --> = --> ( discard )

^ ^
| |
c -> () ----- |
|
|
b -> () -----------

This tree ( and thus operator precedence and operator associativity )
define demonstrativly the order in which some operators are executed (
for example ++ is executed befor *, which is executed befor + ) but
not of all. For example the function call operators c() and b() can be
called in any order, however c() before * and b() befor +.

Side effects are any computation of an operator which is not used to
compute its result (on which other operators depend, i.e. parent nodes
in the tree). For example n++ computes the result n, but as a side
effect it stores n+1 in n. Or n=1 has the result 1, but as side effect
it stores 1 in n. As can be viewn demonstrativly in the tree, side
effects can be executed anywhere between after their operator has been
executed and the sequence point, since they have no operations
depending on them.

Now sequence points define subtrees of a tree. Before the result of
such a subtree (that is the result of the root node) can be used, all
operations (i.e. nodes) of this subtree must have been completed.

Is this view about correct?

I don't know ... you should first look at the thread on comp.std.c++
with subject line "(&++x[0])[0]" and then decide whether your code
produces undefined behavior or not.
 
J

Jerry Coffin

After browsing though many newsgroups articels I'm still not shure how
operator precedence, operator associativity, sequence points, side
effects go together. Currently I have the following view:

An expression
a = b() + c() * d++;

[ ... ]
This tree ( and thus operator precedence and operator associativity )
define demonstrativly the order in which some operators are executed (

[ ... ]
Is this view about correct?

Yes and no. If you're dealing with overloaded operators, then the
expression can all be translated into function calls. For example,
a=b+c(); might come out as a.operator=(b.operator+(c.operator()));

Since a function's argument(s) is/are always evaluated before the
function itself executes, the order of evaluation would be guaranteed.
OTOH, if (for example) you had something overloaded as a global
instead of a member function:

a.operator=(operator+(b, c.operator()));

the order of evaluation is unspecified -- in particular, the two
operands to the operator+ could be evaluated in either order (the
arguments to a function are evaluated before the function itself
executes, but the relative order of evaluation of the arguments is
unspecified).

If you had no overloaded functions (e.g. a, d and the return type from
b() and c() were all int) then there is only ONE sequence point, at
the very end of the expression. In this case, neither precedence nor
associativity tells you _anything_ about order of evaluation --
basically you know that any previous expression is evaluated fully
before evaluation of this one starts, and you know that this one is
fully evaluated before the next one starts. In-between those points,
you know precisely NOTHING. In fact, if you had the same expression in
two different places, you'd have no assurance that both used the same
order of evaluation.

It IS possible to create an expression that includes sequence points
-- for example, 'a && b' has a sequence point between the evaluation
of a and b, so a is always evaluated before b. This has nothing to do
with operator precedence or associativity though -- it's just that the
&& operator is defined to include a sequence point. OTOH, if you
overload operator&&, then you just have a function with two arguments,
which loses the sequence point.
 
R

Ron Natalie

Sensorflo said:
This tree ( and thus operator precedence and operator associativity )
define demonstrativly the order in which some operators are executed (
for example ++ is executed befor *,

The value of the ++ expression is determined, but the change to d is
not defined to happen until you bump into a sequence point. Since order of
operations is unspecified, that could be anytime up until the end of the full
expression.
Side effects are any computation of an operator which is not used to
compute its result

As far as C++ is concerened, it's for only the immediate operands of
the operator.
Now sequence points define subtrees of a tree. Before the result of
such a subtree (that is the result of the root node) can be used, all
operations (i.e. nodes) of this subtree must have been completed.

I'm not sure. It's quite possible that d++ is evaluated but the value
is not known to be stored until a sequence point occurs which might
be one of the function calls. It's not sure that you could express that
span of time as a tree.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top