Remebering the order of precedence

P

Phil Carmody

Keith Thompson said:
[...]

Let me revise my advice:

When in doubt, use parentheses.
Try to be in doubt as rarely as possible.
Sage.

I wouldn't go so far as to avoid *all* redundant parentheses. C has
so many precedence rules that, even if you've memorized them all, it's
likely that anyone reading your code hasn't.

I wish << and >> were closer to * and / in precedence (i.e. I wish
'+' and '-' weren't in between). Because of that, I tend to bracket
most things with combinations of those operators even when I don't
need to.

Phil
 
M

mijoryx

Hi,

Is there a technique to easily remember the order of precedence
of all C operators from high to low priority ?

I think this will save time rather than referring to the chart
for every expression.
Any ideas ?

Thx in advans,
Karthik Balaguru

I've been thinking about this since reading your post
and here's my contribution:

I started with the chart itself and added a description
for each line.
1. () [] -> . explicit access
2. ! ~ ++ -- (type) unary
-(unary) *
& sizeof
3. * / % mul
4. + - add
5. << >> shift
6. < <= > >= g|l t|e glute? glitter?
7. == != (n)eq
8. & (bitwise and) bitand
9. ^ bitxor
10. | bitor
11. && and
12. || or
13. ?: ternary
14. = += -= etc. assign
15. , comma

and recursively on the binaries:
explicit-access unary
(mul add shift math
glitter neq comp
bit(and,xor,or) bits
and or) [[binary]] logic
ternary assign comma.

and finally:
explicit-access unary
binary(math(mul add shift)
comp(glitter neq)
bits(and,xor,or)
logic(and,or))
ternary assign comma.

you can remove the parentheses if you can remember
and before or (xor in the middle)
mul add shift (not too hard)
one applies glitter to a neck, not the other way round.
(the == != is a larger branch of the tree than > <
when both occur at the same syntactic level).
math comp bits logic (say it till it rolls off the tongue)

then it's briefly:
explicit-access unary
binary
ternary assign comma


this should help with concision if nothing else.

luXer-ex-troXX
 
G

Guest

This advice is commonly given, but actually makes the problem
worse rather than better.  Adopting the discipline never to use
redundant parentheses forces the learning to take place.

If one wants to indicate precedence for the benefit of later
readers, another way of doing that is with white space:

    a+b << 2
    a | b<<2

yuk!!! I've never seen code laid out like this and unless
someone told me it wouldn't cross my mind it was supposed to indicate
precedence. to be honest the first thing I'd do is bung it through
indent
 
G

Guest

Keith Thompson said:
Phil Carmody said:
When in doubt, use parentheses.
This advice is commonly given, but actually makes the problem
worse rather than better.  Adopting the discipline never to use
redundant parentheses forces the learning to take place. [...]

Let me revise my advice:
When in doubt, use parentheses.
Try to be in doubt as rarely as possible.
Sage.

I wouldn't go so far as to avoid *all* redundant parentheses.  C has
so many precedence rules that, even if you've memorized them all, it's
likely that anyone reading your code hasn't.

I wish << and >> were closer to * and / in precedence (i.e. I wish
'+' and '-' weren't in between). Because of that, I tend to bracket
most things with combinations of those operators even when I don't
need to.

don't mix logical and aritmetic operators. For instance if you wrote
this
x = a << 8 + b;

as
x = a << 8 | b;

or even
x = a * 256 + b;

then the problem would never arise
 
P

Phil Carmody

don't mix logical and aritmetic operators. For instance if you wrote
this
x = a << 8 + b;

as
x = a << 8 | b;

or even
x = a * 256 + b;

then the problem would never arise

This is indeed also sage. I've programmed for enough architectures
where you really don't want to be setting things like carry flags
unnecessarily as doing so could prevent instruction re-ordering,
that I'm surprised I don't do that already. I suspect I do. I'll
have to look at the last bit of code that I originate rather than
just diddled with...

Phil
 
T

Tim Rentsch

yuk!!! I've never seen code laid out like this and unless
someone told me it wouldn't cross my mind it was supposed to indicate
precedence. to be honest the first thing I'd do is bung it through
indent

Yes, isn't it wonderful how reading comp.lang.c can broaden
one's horizons.
 
D

David Thompson

(to avoid one class of precedence problems)

_bitwise_ and arithmetic, as already noted.
This would be better advice if one didn't need to type

(1 << n) - 1

so damnably often.
Assuming you want unsigned, as you usually do for bit manipulation, or
at least can accept it; or you rely on the common but not strictly
standard 2sC-ignore-overflow behavior of signed:
~ ( ~0U << n ) /* or -1U but I like to be all-bitwise */

plus I often hide this in a macro so the issue of typing it doesn't
matter anyway (but I'm still USING it, which is also important).
 
D

David Thompson

Postfix funcall, arraysub, dot, and arrow; and ++ --
ABOVE unary e.g. the very common *p++
The latter yes, but not the former. Arithmetic treats negation as
additive, but since (add,mul) are a field it never makes a difference.
Except for artifacts of (computer) typing, e.g. in C unsigned vs
signed, only with exponentiation added can you tell the difference.
And in Fortran, which has exponentiation (and as the first language
designed for numerics tried to follow math as well as it could)
negation binds with add&sub and - X ** Y is - (X**Y) not (-X)**Y .
(And so does unary + for symmetry, although it accomplishes nothing.)
And then it would have a (minor) problem vs math. But it doesn't.
Comparison below arith, and logic lower yet, I concur.
And similarly & | but ^ is not so intuitive to me.

(Most?) Other 3GLs have assignment as a statement not an operator, and
hence 'below the bottom' of the operator precedence list. Putting it
above comma and incomparable with ?: is close enough for me.
See below.
Mostly I agree with the above, but there are two or three notable
exceptions.

The least notable exception is the shift operators, which seem
natural to put in with the multiply-level operators.

At the other end of the precedence scale, to me assignment makes
sense where it is. All the operators above it (not counting ++
and --) yield values without side-effects, and you want to do
something with the value, so assignment should be right near the
bottom so those values can be stored. The one operator below
assignment, comma, clearly seems designed to partition operators
that have side-effects, so it naturally goes below assignment.

The precedence choice that seems most wrong is the bitwise boolean
operators; these would be better just above the comparison
operators (both relational and equality), rather than just below.
I remember reading somewhere that Dennis Ritchie said he would
change that now if he could (originally C didn't have && and ||)
but of course it's too late now to change it.

Concur with both: they would have been nicer above comparison, but
historically it couldn't have happened.
 

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,771
Messages
2,569,587
Members
45,099
Latest member
AmbrosePri
Top