operator precedence with && and comma

S

siliconwafer

Hi,
In case of following expression:
c = a && --b;
if a is 0,b is not evaluated and c directly becomes 0.
Does this mean that && operator is given a higher precedence over
'--'operator?
as opposed to what is mentioned in precedence table?
Also,
with comma operator.
consider,
a= b,a = a*4,a = a/5;
Here,
order of precedence according to precedence table is / then * then =
and last comma.but will be from left to right in practice.This is like
writing seperate statements from left to right.
Does this mean that comma is given the hiegest precedence over other
operators.if so it should sit at the top of precedence.
any light on the subject will be highly helpful to clear the anamoly.
-siliconwafer
 
E

Eric Sosman

siliconwafer said:
Hi,
In case of following expression:
c = a && --b;
if a is 0,b is not evaluated and c directly becomes 0.
Does this mean that && operator is given a higher precedence over
'--'operator?

No.
as opposed to what is mentioned in precedence table?

Believe the table.
Also,
with comma operator.
consider,
a= b,a = a*4,a = a/5;
Here,
order of precedence according to precedence table is / then * then =
and last comma.but will be from left to right in practice.This is like
writing seperate statements from left to right.
Does this mean that comma is given the hiegest precedence over other
operators.if so it should sit at the top of precedence.
any light on the subject will be highly helpful to clear the anamoly.

You're misunderstanding the term "precedence." To
get back on familiar ground, consider `a+b*c'. Which of
+ and * has higher precedence: the one that's "executed
first" or the one that's "executed last?"

However, the whole business is a red herring. Precedence
and associativity (which are really just a convenient short-
hand for the grammar in the language Standard) determine the
meaning of expressions, but do not determine the order of
evaluation. The fact that && "short-circuits" the evaluation
is a property of the && operator itself, not of its precedence
as compared to other operators. Consider: `0 * --x' does not
short-circuit, even though the precedence relations are just
the same.

The operators && and || and , and ?...: provide some special
guarantees about sequencing and short-circuiting; these have
nothing to do with their precedence or associativity.
 
C

Chris Dollin

siliconwafer said:
Hi,
In case of following expression:
c = a && --b;
if a is 0,b is not evaluated and c directly becomes 0.
Does this mean that && operator is given a higher precedence over
'--'operator?

No. Precedence is a separate concept from order-of-evaluation.
Precedence is just a way of dsescribing which expressions are
operands to which other expressions.
with comma operator.
consider,
a= b,a = a*4,a = a/5;
Here,
order of precedence according to precedence table is / then * then =
and last comma.

So comma is the most weakly binding; everying else are operands
to comma.
but will be from left to right in practice.

The *order of evaluation" of a comma-expression `A, B` is
to evaluate A first, then evaluate B. Precedence has nothing to do
with it.
 
S

siliconwafer

Chris said:
No. Precedence is a separate concept from order-of-evaluation.
Precedence is just a way of dsescribing which expressions are
operands to which other expressions.


So comma is the most weakly binding; everying else are operands
to comma.


The *order of evaluation" of a comma-expression `A, B` is
to evaluate A first, then evaluate B. Precedence has nothing to do
with it.



Hi chris,
So if 'precedence' is different that 'order of evaluation',does it mean
that order of evaluation is always from left to right,no matter what
the associativiy/precedence indicate?
If so,when does the 'order' of && or , matter and when does their
'precedence'matter?
 
M

Michael Mair

siliconwafer said:
Hi chris,
So if 'precedence' is different that 'order of evaluation',does it mean
that order of evaluation is always from left to right,no matter what
the associativiy/precedence indicate?

Not at all. They can be evaluated in arbitrary order between
to sequence point -- this is the reason why it is not allowed
to modify the same variable twice between sequence points, e.g.
b = a++ * a++;
has no defined behaviour. See the FAQ for more about sequence
points. This can introduce subtle bugs:
Consider a stack: pop() returns the value from the
top of the stack and removes the top element.
If we have a stack with value a on the top and value b below it,
then
pop() - pop()
can either give us a - b or b - a; it may be that it "works"
for years on end as intended, say a-b but then you switch to
another compiler or platform -- and suddenly you get the additive
inverse...
If so,when does the 'order' of && or , matter and when does their
'precedence'matter?

&& and || and , introduce sequence points.
Think of them like
/* pseudocode */
AND (a, b) :
if (!a)
return 0;
else
return b;
OR (a, b) :
if (a)
return 1;
else
return b;
COMMA (a, b) :
a;
ret = b;
return ret;

The precedence matters whenever applicable:
Say you want to check whether a equals b and at the same time c holds:
if (a==b && c)
then the precedence of == is higher than that of &&, so we need no
parentheses, i.e. it is equivalent to
if ((a==b) && c)
If we want to store the evaluation of b into a and, if a is true, want
to check that c holds, we need
if ( (a=b) && c)
as the precedence of && is higher than the precedence of =. If we leave
out the parentheses,
if (a = b && c)
then we obtain the same as
if (a = (b && c))
i.e., if b is true, then c is evaluated (which is the same situation
as before) but a can now have either the values 0 or 1 (these are
the possible "return" values of &&)

Cheers
Michael
 
G

Gordon Burditt

So if 'precedence' is different that 'order of evaluation',does it mean
that order of evaluation is always from left to right,no matter what
the associativiy/precedence indicate?

Precedence determines which operands go with which operators. For
example, in the expression a*b+c*d, the two operands of + are (a*b)
and (c*d), *NOT* b and c. Precedence can be made irrelevant by
using enough parentheses in the right places.
If so,when does the 'order' of && or , matter and when does their
'precedence'matter?

Order of evaluation is partially determined by the rule: you can't
evaluate an operator until its operands have been evaluated (except
in the case of certain C operators which specify otherwise, like
comma, &&, ||, and ?:, which either dictate an order or specify
that under some circumstances some of the operands may not be
evaluated at all). If you try, you'll find you have insufficient
information to do the operation at this point.

Thus, you have to do both a*b and c*d before (a*b)+(c*d), but this
does *NOT* mean that a*b is evaluated before c*d.

Gordon L. Burditt
 
J

John Bode

siliconwafer said:
Hi chris,
So if 'precedence' is different that 'order of evaluation',does it mean
that order of evaluation is always from left to right,no matter what
the associativiy/precedence indicate?

Order of evaluation is not always left to right. The comma operator
and the || and && operators are special in that they force a particular
order of evaluation. In general, however, order of evaluation isn't
specified, and is independent of precedence and associativity. For
example, in the expression

a() + b() * c() - d()

the * operator has higher precedence than either the + or - operator,
so the result will be the return values of b() and c() multiplied
together, added to the return value of a(), minus the return value of
d(). However, the actual order in which a(), b(), c() and d() are
executed is not specified, and the compiler is free to arrange those
calls any way it sees fit, as long as the final result obeys the rules
of precedence.

If we have something like

a() < b() || c() >= d() && e() == f()

the || operator guarantees that both a() and b() will be executed
before either of c(), d(), e() or f(), but there's no guarantee that
a() will be executed before b(). && has a higher precedence than ||,
so the expression is evaluated as

a() < b() || (c() >= d() && e() == f())

IOW, the result of the expression is true when either

a() < b()

or

c() >= d() && e() == f()

evaluate to true.
If so,when does the 'order' of && or , matter and when does their
'precedence'matter?

Order of evaluation matters is when you have side effects. Precedence
matters when you want the right result.
 
C

CBFalconer

John said:
.... snip ...

Order of evaluation matters is when you have side effects.
Precedence matters when you want the right result.

Also when the possibility of intermediate overflows exists.

INT_MAX + 3 - 4

will overflow if the addition precedes the subtraction.
 
P

Peter Nilsson

Your reply (below) seems to relate to this statement. That you
left John's next statement only makes your reply ambiguous
since you discus an issue of associativity, not precedence.
Also when the possibility of intermediate overflows exists.

INT_MAX + 3 - 4

will overflow if the addition precedes the subtraction.

Binary + and - have the _same_ precedence.

For those who aren't sure, the expression above is undefined
since the the additive operators associate from left to right.
Thus, even though the net mathematical value is within the
range of an int, the sub-expression INT_MAX + 3 invokes
undefined behaviour due to the overflow.

[Actual cases of this have occured in clc, where an author has
incorrectly used...

n = n * 10 + digit - '0';

....instead of...

n = n * 10 + (digit - '0');
]
 
C

CBFalconer

Peter said:
.... snip ...


Binary + and - have the _same_ precedence.

So what? Precedence (which doesn't exist [1]) does not define
order of evaluation, and the compiler is free to generate code in
any order it prefers. Rewriting the above as "INT_MAX - 4 + 3"
won't improve the situation at all. Just because 9 out of 10
systems will quietly generate a correct end result doesn't make it
correct. The tenth may well crash. The safe method is to use a
temporary and ensure that no overflow can ever occur.

[1] The standard only imposes a BNF standard, apparent precedence
and associativity is derived from this.
 
C

Chris Dollin

siliconwafer said:
Hi chris,
So if 'precedence' is different that 'order of evaluation',

Which it is. Precedence is a shorthand way of describing which operands
are operands of which operators - and that's all. It's just syntax.
It says that in the expression

x + y * z

the operands of `*` are `x + y` and `z` (in that order), and the
operands of `+` are `x` and `y` (ditto). The related notion of
(syntactic) associativity [1] does the same job when the operators
are the *same* operator: in

x - y - z

the operands of the first `-` are `x` and `y`, of the second are
`x - y` and `z`.
does it mean
that order of evaluation is always from left to right,
no matter what the associativiy/precedence indicate?

No, it doesn't. It means the order of evaluation is whatever the
order of evaluation is. A decent guide is this: the operands of
an operator, if they are evaluated at all, are evaluated before
the operator itself is.
If so,when does the 'order' of && or , matter and when does their
'precedence'matter?

For *most* C operators, the order of evaluation of operands is
not specified /at all/; the implementation is free to pick an
order, or to interleave the operand evaluation. Thus in

x + y * z

any of x, y, and z may be evaluated first, and any of the rest
second, or (on a suitable machine) they might be evaluated in
parallel.

For && and ||, there is a specific order defined: evaluate the
left operand only; only evaluate the right operand if required
for the correct answer. Similarly for ?:, there is a specific
order: evaluate the first operand, then evaluate only the
appropriate one of the other two.

For the *comma operator* [2] the rule is: evaluate the first
argument, ignore the result, evaluate the second argument, which
is the result.

Note that `precedence` isn't mentioned in the evaluation order
rules, because it doesn't need to be.

[1] Not to be confused with the semantic notion of an operator being
`associative`, meaning that (x op y) op z = x op (y op z).

[2] *Not* the arguments to functions; those commas are not comma-
operators.
 
S

siliconwafer

John said:
Order of evaluation is not always left to right. The comma operator
and the || and && operators are special in that they force a particular
order of evaluation. In general, however, order of evaluation isn't
specified, and is independent of precedence and associativity. For
example, in the expression

a() + b() * c() - d()

the * operator has higher precedence than either the + or - operator,
so the result will be the return values of b() and c() multiplied
together, added to the return value of a(), minus the return value of
d(). However, the actual order in which a(), b(), c() and d() are
executed is not specified, and the compiler is free to arrange those
calls any way it sees fit, as long as the final result obeys the rules
of precedence.

If we have something like

a() < b() || c() >= d() && e() == f()

the || operator guarantees that both a() and b() will be executed
before either of c(), d(), e() or f(), but there's no guarantee that
a() will be executed before b(). && has a higher precedence than ||,
so the expression is evaluated as

a() < b() || (c() >= d() && e() == f())

IOW, the result of the expression is true when either

a() < b()

or

c() >= d() && e() == f()

evaluate to true.


Order of evaluation matters is when you have side effects. Precedence
matters when you want the right result.



Hi,
" a() + b() * c() - d() ":
Here,
after evaluation of b()*c(),
say,
temp = b() * c();
expression reduces to
a() + temp - d();
Now is the order from left to right garunteed by associativity?
i.e + and - have same precedence and associativity from left to right.
so '+' wins over '-' to claim its authority over temp so expression is
evaluated as:
temp1 = a() + temp;
temp1 - d();
So is the order of evaluation garunteed now or is it still compiler
dependant?
-Siliconwafer
 
R

Robert Gamble

CBFalconer said:
Peter said:
... snip ...


Binary + and - have the _same_ precedence.

So what? Precedence (which doesn't exist [1]) does not define
order of evaluation, and the compiler is free to generate code in
any order it prefers.

Only if doing so will not affect the result.
Rewriting the above as "INT_MAX - 4 + 3"
won't improve the situation at all.

Yes it will. The expression must be evaluated as if it were written
(INT_MAX - 4) + 3 which is completely safe.
Just because 9 out of 10
systems will quietly generate a correct end result doesn't make it
correct. The tenth may well crash.

The tenth system is defective.
The safe method is to use a
temporary and ensure that no overflow can ever occur.

Nonsense.

Robert Gamble
 
A

Anonymous 7843

" a() + b() * c() - d() ":
Here,
after evaluation of b()*c(),
say,
temp = b() * c();
expression reduces to
a() + temp - d();
Now is the order from left to right garunteed by associativity?
i.e + and - have same precedence and associativity from left to right.
so '+' wins over '-' to claim its authority over temp so expression is
evaluated as:
temp1 = a() + temp;
temp1 - d();
So is the order of evaluation garunteed now or is it still compiler
dependant?
-Siliconwafer

The compiler is free to implement it as

temp2 = b();
temp4 = d();
temp1 = a();
temp3 = c();
temp5 = temp1 + (temp2 * temp3) - temp4;

The actual order of evaluation and the precedence/associativity
of the results are completely unrelated in this case.

Only the specific operators that define an order of evaluation
are guaranteed to do so.
 
J

John Bode

siliconwafer said:
Hi,
" a() + b() * c() - d() ":
Here,
after evaluation of b()*c(),
say,
temp = b() * c();
expression reduces to
a() + temp - d();
Now is the order from left to right garunteed by associativity?

No. Read this bit again:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Given the expression a() + temp - d(), there is no guarantee, *none*,
that a() will be *evaluated* before d(). All that is guaranteed is
that the *result* of a() will first be added to temp, and that the
*result* of d() will be subtracted from that total.

Going back to the original expression, it could be evaluated as:

t1 <- b() * c()
t2 <- d()
t3 <- t1 + a()
t4 <- t3 - t2

Or even as:

t1 <- a()
t2 <- d()
t3 <- c()
t4 <- b() * t3
t5 <- t4 + t1
t6 <- t5 - t2

Even if you write

(a() + b()) * c() - d()

that doesn't mean the compiler won't arrange the functions to be called
in the order d(), a(), c(), and b().

The *only* times you can rely on a specific order of evaluation are
with the ||, &&, and comma operators. In all three cases, they will
evaluate their left operand before evaluating their right operand. And
to repeat myself again:
 
P

pete

CBFalconer said:
Peter said:
... snip ...


Binary + and - have the _same_ precedence.

So what? Precedence (which doesn't exist [1])

It's not really important that it doesn't exit.
Both precedence and associativity are useful concepts.
Everybody who knows what's on page 53,
without me mentioning which book, raise your hand.
does not define
order of evaluation, and the compiler is free to generate code in
any order it prefers. Rewriting the above as "INT_MAX - 4 + 3"
won't improve the situation at all.

There's nothing wrong with (INT_MAX - 4 + 3)
Associativity is left to right for + -
((INT_MAX - 4) + 3)
 
P

pete

Peter said:
Your reply (below) seems to relate to this statement. That you
left John's next statement only makes your reply ambiguous
since you discus an issue of associativity, not precedence.
Also when the possibility of intermediate overflows exists.

INT_MAX + 3 - 4

will overflow if the addition precedes the subtraction.

Binary + and - have the _same_ precedence.

For those who aren't sure, the expression above is undefined
since the the additive operators associate from left to right.
Thus, even though the net mathematical value is within the
range of an int, the sub-expression INT_MAX + 3 invokes
undefined behaviour due to the overflow.

[Actual cases of this have occured in clc, where an author has
incorrectly used...

n = n * 10 + digit - '0';

...instead of...

n = n * 10 + (digit - '0');
]

This
n = n * 10 - '0' + digit;
would have been OK.

It looks like the "n is nonnegative" case, from atoi.
 
C

Chris Dollin

John said:
The *only* times you can rely on a specific order of evaluation are
with the ||, &&, and comma operators.

Have you not made a mistake? Namely: the conditional expression.
 

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

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,046
Latest member
Gavizuho

Latest Threads

Top