Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #141843
| 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) |
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
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