Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #141843

Remembering C's operator precedence rules

From Ben Bacarisse <ben.usenet@bsb.me.uk>
Newsgroups comp.lang.c
Subject Remembering C's operator precedence rules
Date 2019-03-09 16:53 +0000
Organization A noiseless patient Spider
Message-ID <87lg1o9efx.fsf@bsb.me.uk> (permalink)

Show all headers | View raw


I was going to post this as a reply, but once finished I thought it
should be a new thread.

Prompted by recent posts about remembering C's 15 precedence levels for
its 49 operators, I thought I would gather together some remarks about
why I think you can work most of it out for yourself.  I certainly don't
know them all, but I think of them in big blocks (unary, arithmetic,
relational, and so on) which are easy to relate to each other, and only
every now and then do I need to consider the structure within these
blocks of operators.

It's obvious that all the postfix operators will be grouped together in
one level, as will the prefix operators.  What would multiple levels of
prefix operator even mean?  It simply would not make sense to have more
than one level for each group.  Similarly, the two groups must be
separate.  However, which group is higher can be remembered because it's
natural.  Consider

  -sin(x)
  *s.member
  &a[1]

You would not want to have to write

  -(sin(x))
  *(s.member)
  &(a[1])

to get the desired result for these common forms.  If you need another
clue, remember that -> is provided precisely because you'd have to write
(*p).member otherwise.

The structure within the arithmetic operators is easy as we all learn it
in school.  You just have to remember to include % as a multiplicative
operator.

And you can extend that, by analogy, to & binding tighter than | and &&
tighter than ||.  This may be more natural for mathematically inclined
programmers, but I think the convention is common in electronic
engineering circles too.  The fact that ^ has it's own level between &
and | is so rarely remembered that it's not one I'd blithely assume
everyone knows.  I never remember it, except when I'm writing things
like this.

Within the big block of relational operators, another grouping that
looks odd at first is that == and != have their own precedence level
just below <, >, <= and >=.  This is another case that it's probably
wise to assume not everyone knows, but /you/ might remember it if you
consider that == and != make sensible logical connectives, rather like
&& and ||.  For example, to test if four variables are in order --
either ascending or descending -- you can write

  a <= b  ==  b <= c  ==  c <= d

Compare that with

  a <= b  &&  b <= c  &&  c <= d

for a single order.

There's no reason for the assignment operators to be in more than one
group, and they must bind very low since almost any expression should be
permitted without () on the right hand side of an assignment.  The
exception is the comma operator, but again, that's natural.  It acts
like ; for statements so any expression, even assignments, should
un-parenthesised within a comma expression.

So what's left?  Well there's << and >> and the conditional operator.
These are arithmetic in nature (I'm using the term more loosely here,
not as in arithmetic vs logical shift) so they will be somewhere in
amongst *, /, + and so on.  However, I need a cue to remember that the
shift operators come just below addition.  The fact that C++ uses them
for streams does the trick for me.  You could not naturally write

  std::cout << x + 1

otherwise.

The conditional operator is so different it needs a switch in
perspective.  Because the ? and : can, unambiguously, delimit any
expression, you can make it fit the pattern of the others if you
consider ?<exp>: to be a single binary operator.  Obviously you want it
to bind very loosely (below the logical connectives that will often
occur in the condition), but should it be above or below assignment?  To
work it out, I ask which form is more common:

  <cond> ?<exp>: var = val

or

  var = <cond> ?<exp>: val

I think I write the second much more than the first, and it is indeed
that form that needs no parentheses.  (As written, the first is a
constraint violation.  To get the assignment /in/ the conditional you
need to write <cond> ?<exp>: (var = val).)

Finally, is the overall relationship between the big blocks of operators
logical?  By and large I think it is.  The unary operators must come
top, and comma and assignment must come bottom.  Between these, the
arithmetic operators must come above the relational operators, and these
much come above the logical connectives.  The fly in the ointment
(acknowledged by DMR as an unfortunate import from B) is that &, ^ and |
sit rather unnaturally low.  They were used as logical connectives as
well as bit-wise operators in B, so it's not too hard to remember that
they are low, but still, it's not ideal.

So how do you either remember these, or work them out from first
principles?  Do you have any handy mnemonics or idiomatic examples to
share?

-- 
Ben.

Back to comp.lang.c | Previous | Next — Next in thread | Find similar | Unroll thread


Thread

Remembering C's operator precedence rules Ben Bacarisse <ben.usenet@bsb.me.uk> - 2019-03-09 16:53 +0000
  Re: Remembering C's operator precedence rules Richard Damon <Richard@Damon-Family.org> - 2019-03-09 15:21 -0500
    Re: Remembering C's operator precedence rules Ben Bacarisse <ben.usenet@bsb.me.uk> - 2019-03-09 21:41 +0000
  Re: Remembering C's operator precedence rules Keith Thompson <kst-u@mib.org> - 2019-03-09 12:32 -0800
    Re: Remembering C's operator precedence rules Ben Bacarisse <ben.usenet@bsb.me.uk> - 2019-03-09 21:21 +0000
      Re: Remembering C's operator precedence rules Richard Damon <Richard@Damon-Family.org> - 2019-03-09 16:42 -0500
        Re: Remembering C's operator precedence rules "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2019-03-09 14:01 -0800
      Re: Remembering C's operator precedence rules Keith Thompson <kst-u@mib.org> - 2019-03-09 14:17 -0800
        Re: Remembering C's operator precedence rules Ben Bacarisse <ben.usenet@bsb.me.uk> - 2019-03-10 00:42 +0000
  Re: Remembering C's operator precedence rules Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2019-03-09 13:54 -0700
    Re: Remembering C's operator precedence rules Bart <bc@freeuk.com> - 2019-03-09 21:37 +0000
      Re: Remembering C's operator precedence rules Ben Bacarisse <ben.usenet@bsb.me.uk> - 2019-03-09 22:01 +0000
      Re: Remembering C's operator precedence rules Richard Damon <Richard@Damon-Family.org> - 2019-03-09 18:59 -0500
        Re: Remembering C's operator precedence rules Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-03-13 09:26 -0700
    Re: Remembering C's operator precedence rules Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-03-13 10:11 -0700
      Re: Remembering C's operator precedence rules Bart <bc@freeuk.com> - 2019-03-13 17:40 +0000
        Re: Remembering C's operator precedence rules Keith Thompson <kst-u@mib.org> - 2019-03-13 15:24 -0700
          Re: Remembering C's operator precedence rules Bart <bc@freeuk.com> - 2019-03-13 23:43 +0000
            Re: Remembering C's operator precedence rules Keith Thompson <kst-u@mib.org> - 2019-03-13 17:43 -0700
        Re: Remembering C's operator precedence rules Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-03-18 08:53 -0700
      Re: Remembering C's operator precedence rules Wouter Verhelst <w@uter.be> - 2019-03-13 22:24 +0200
        Re: Remembering C's operator precedence rules Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-03-13 14:06 -0700
        Re: Remembering C's operator precedence rules Ian Collins <ian-news@hotmail.com> - 2019-03-14 14:28 +1300
          Re: Remembering C's operator precedence rules scott@slp53.sl.home (Scott Lurndal) - 2019-03-14 13:35 +0000
            Re: Remembering C's operator precedence rules Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2019-03-14 06:55 -0700
            Re: Remembering C's operator precedence rules Ben Bacarisse <ben.usenet@bsb.me.uk> - 2019-03-14 16:39 +0000
              Re: Remembering C's operator precedence rules scott@slp53.sl.home (Scott Lurndal) - 2019-03-14 17:37 +0000
                Re: Remembering C's operator precedence rules Ben Bacarisse <ben.usenet@bsb.me.uk> - 2019-03-14 20:42 +0000
              Re: Remembering C's operator precedence rules Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2019-03-14 10:42 -0700
                Re: Remembering C's operator precedence rules Ben Bacarisse <ben.usenet@bsb.me.uk> - 2019-03-14 23:08 +0000
                Re: Remembering C's operator precedence rules Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2019-03-15 02:53 -0700
                Re: Remembering C's operator precedence rules Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2019-03-15 17:52 -0600
  Re: Remembering C's operator precedence rules Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-03-13 12:56 -0700
  Re: Remembering C's operator precedence rules Jens Stuckelberger <Jens_Stuckelberger@nowhere.net> - 2019-03-13 20:14 +0000
  Re: Remembering C's operator precedence rules fir <profesor.fir@gmail.com> - 2019-03-19 14:17 -0700

csiph-web