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


Groups > comp.lang.c > #141843 > unrolled thread

Remembering C's operator precedence rules

Started byBen Bacarisse <ben.usenet@bsb.me.uk>
First post2019-03-09 16:53 +0000
Last post2019-03-19 14:17 -0700
Articles 20 on this page of 35 — 13 participants

Back to article view | Back to comp.lang.c


Contents

  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

Page 1 of 2  [1] 2  Next page →


#141843 — Remembering C's operator precedence rules

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2019-03-09 16:53 +0000
SubjectRemembering C's operator precedence rules
Message-ID<87lg1o9efx.fsf@bsb.me.uk>
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.

[toc] | [next] | [standalone]


#141845

FromRichard Damon <Richard@Damon-Family.org>
Date2019-03-09 15:21 -0500
Message-ID<_eVgE.15123$sd4.6824@fx48.iad>
In reply to#141843
On 3/9/19 11:53 AM, Ben Bacarisse wrote:
> For example, to test if four variables are in order --
> either ascending or descending -- you can write
> 
>   a <= b  ==  b <= c  ==  c <= d

That doesn't work for descending order,
     false == false == false
becomes
     true == false
becomes
     false

[toc] | [prev] | [next] | [standalone]


#141850

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2019-03-09 21:41 +0000
Message-ID<878sxnafpl.fsf@bsb.me.uk>
In reply to#141845
Richard Damon <Richard@Damon-Family.org> writes:

> On 3/9/19 11:53 AM, Ben Bacarisse wrote:
>> For example, to test if four variables are in order --
>> either ascending or descending -- you can write
>> 
>>   a <= b  ==  b <= c  ==  c <= d
>
> That doesn't work for descending order,
>      false == false == false
> becomes
>      true == false
> becomes
>      false

Yes, and it returns 1 in all sorts of cases it shouldn't as well!  I was
dimly remembering the three variable case:

 a <= b  ==  b <= c

It's all wrong for four.  You can correct it with another test and an &&

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

but that's not neat enough to act as a reminder.

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#141846

FromKeith Thompson <kst-u@mib.org>
Date2019-03-09 12:32 -0800
Message-ID<lna7i3lrf0.fsf@kst-u.example.com>
In reply to#141843
Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
[...]
> 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.

I think you forgot about associativity.
    x == y == z
means
    (x == y) == z
not
    (x == y) && (y == z)

(Some languages do chain comparison operators, and some forbid
expressions that would be ambiguous.  C just sits back and lets you
shoot yourself in the foot.)

[...]

> 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?

I usually have a copy of n1570.pdf open.  When necessary, look at the
table of contents and check the subsection names in section 6.5.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Will write code for food.
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#141848

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2019-03-09 21:21 +0000
Message-ID<87ftrvaglt.fsf@bsb.me.uk>
In reply to#141846
Keith Thompson <kst-u@mib.org> writes:

> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
> [...]
>> 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.
>
> I think you forgot about associativity.
>     x == y == z
> means
>     (x == y) == z
> not
>     (x == y) && (y == z)

Thanks.  I should have looked for a better example as this one gets
messy when corrected.  Do you know of an example that would motivate the
otherwise rather surprising separation between relational an equality
operators?

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#141851

FromRichard Damon <Richard@Damon-Family.org>
Date2019-03-09 16:42 -0500
Message-ID<5rWgE.190267$%l2.181350@fx42.iad>
In reply to#141848
On 3/9/19 4:21 PM, Ben Bacarisse wrote:
> Keith Thompson <kst-u@mib.org> writes:
> 
>> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>> [...]
>>> 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.
>>
>> I think you forgot about associativity.
>>     x == y == z
>> means
>>     (x == y) == z
>> not
>>     (x == y) && (y == z)
> 
> Thanks.  I should have looked for a better example as this one gets
> messy when corrected.  Do you know of an example that would motivate the
> otherwise rather surprising separation between relational an equality
> operators?
> 

It works for 3 numbers, just not 4.

[toc] | [prev] | [next] | [standalone]


#141852

From"Rick C. Hodgin" <rick.c.hodgin@gmail.com>
Date2019-03-09 14:01 -0800
Message-ID<66163672-fa48-46d7-a228-9cb03a416e9c@googlegroups.com>
In reply to#141851
It's easy to remember.  Just use a reference:

    https://en.cppreference.com/w/c/language/operator_precedence

-- 
Rick C. Hodgin

[toc] | [prev] | [next] | [standalone]


#141854

FromKeith Thompson <kst-u@mib.org>
Date2019-03-09 14:17 -0800
Message-ID<ln5zsrlmju.fsf@kst-u.example.com>
In reply to#141848
Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
> Keith Thompson <kst-u@mib.org> writes:
>> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>> [...]
>>> 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.
>>
>> I think you forgot about associativity.
>>     x == y == z
>> means
>>     (x == y) == z
>> not
>>     (x == y) && (y == z)
>
> Thanks.  I should have looked for a better example as this one gets
> messy when corrected.  Do you know of an example that would motivate the
> otherwise rather surprising separation between relational an equality
> operators?

You could use the same method to determine whether 3 values are in
either ascending or descending order:
    a <= b == b <= c
It just breaks down when you need more than one "==" operator.

(I'd parenthesize that myself.)

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Will write code for food.
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#141859

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2019-03-10 00:42 +0000
Message-ID<87tvgb8squ.fsf@bsb.me.uk>
In reply to#141854
Keith Thompson <kst-u@mib.org> writes:
<cut>
> You could use the same method to determine whether 3 values are in
> either ascending or descending order:
>     a <= b == b <= c
> It just breaks down when you need more than one "==" operator.

Yes, that was the example I was remembering, but on its own, it seems
rather weak as a justification for splitting == and !== off from <, <=
et. al.  Is equality testing of relations more widely useful?  I don't
think I've used it more than maybe once or twice in many decades.

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#141847

FromJoe Pfeiffer <pfeiffer@cs.nmsu.edu>
Date2019-03-09 13:54 -0700
Message-ID<1bh8cb93bi.fsf@pfeifferfamily.net>
In reply to#141843
Ben Bacarisse <ben.usenet@bsb.me.uk> writes:

> 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.

<snip>

This isn't unexpected; they are in the order that seemed most intuitive
to K&R in 1974 or thereabouts (doing something like putting + above *
would have been downright perverse).

The thing is, what's most intuitive depends on everything from context
in the program to the current phase of the moon.  By the time you've got
15 levels for 49 operators, any sane programmer will be putting in some
extra parentheses here and there because it's faster than googling to
find out if they're necessary, and if I don't remember for sure in my
own code it probably isn't fair to expect someone coming along later
(possibly even me under a full moon) to have the same intuition.

[toc] | [prev] | [next] | [standalone]


#141849

FromBart <bc@freeuk.com>
Date2019-03-09 21:37 +0000
Message-ID<UmWgE.67704$U64.2717@fx20.am4>
In reply to#141847
On 09/03/2019 20:54, Joe Pfeiffer wrote:
> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
> 
>> 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.
> 
> <snip>
> 
> This isn't unexpected; they are in the order that seemed most intuitive
> to K&R in 1974 or thereabouts (doing something like putting + above *
> would have been downright perverse).

That doesn't explain why there are so many.

WHY do &, | and ^ each need, not only a separate level from all other 
operators, but even separate from each other?! What could possibly be 
the advantage?

> The thing is, what's most intuitive depends on everything from context
> in the program to the current phase of the moon.

There is nothing intuitive about C's operators apart from the 4 levels 
that everyone should know:

    * /        (from school)
    + -
    == etc     (from use of 'equals' in school)
    &&         (from use of 'and' in English)

One more level for || needs to be added (I don't know the reasoning for 
that one although I can guess), but after that there was no reason for 
any more really:

All compare operators can share with ==.

All <<, >> that scale numbers so do a similar job, can go with * and / 
(throw % in there too).

All others (I'm excluding assignment), since they don't do scaling, and 
they are not compare ops, can be lumped in with + and -. Job done.

As for the rest, some I don't consider operators, so it's a question of 
syntax, not precedence.

[toc] | [prev] | [next] | [standalone]


#141853

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2019-03-09 22:01 +0000
Message-ID<87zhq3906t.fsf@bsb.me.uk>
In reply to#141849
Bart <bc@freeuk.com> writes:

> On 09/03/2019 20:54, Joe Pfeiffer wrote:
>> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>>
>>> 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.
>>
>> <snip>
>>
>> This isn't unexpected; they are in the order that seemed most intuitive
>> to K&R in 1974 or thereabouts (doing something like putting + above *
>> would have been downright perverse).
>
> That doesn't explain why there are so many.
>
> WHY do &, | and ^ each need, not only a separate level from all other
> operators, but even separate from each other?! What could possibly be
> the advantage?

The advantage could possibly be having to use fewer ()s.  Note (because
I know how you flip arguments around) that I am not saying that there is
no associated disadvantage.  Another might be to allow the language to
gain operators during its development without breaking any old code.
That is explanation given for two of them.

>> The thing is, what's most intuitive depends on everything from context
>> in the program to the current phase of the moon.
>
> There is nothing intuitive about C's operators apart from the 4 levels
> that everyone should know:
>
>    * /        (from school)
>    + -
>    == etc     (from use of 'equals' in school)
>    &&         (from use of 'and' in English)

That unary operators are above these is also, I suspect, intuitive even
to you.  And I can't see how you could argue that having pre- and
post-fix operators separate, and in the order they come, is not also
intuitive.  What else could be done with them without making code clumsy.

> One more level for || needs to be added (I don't know the reasoning
> for that one although I can guess), but after that there was no reason
> for any more really:

Where do assignment operators come?  If you put them in with something
else you might still need another rule because assignment should be
right-associative and most other groups should probably associate to the
left.

So what would be your preferred table?

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#141858

FromRichard Damon <Richard@Damon-Family.org>
Date2019-03-09 18:59 -0500
Message-ID<zrYgE.56434$Ar5.42856@fx37.iad>
In reply to#141849
On 3/9/19 4:37 PM, Bart wrote:
> 
> WHY do &, | and ^ each need, not only a separate level from all other
> operators, but even separate from each other?! What could possibly be
> the advantage?

Convention from the domain that created them. Just as in algebra we
treat w*x+y*z as (w*x)+(y*z) in Boolean Algebra w&x|y&Z is assumed to
mean (w&x)|(y&Z), and xor is in the middle so w&x^y&z does the xor last,
and w^x|y^z does the or last.

It also comes in handy when building up a word for a device register
from the component parts, mask each variable with the field mask it is
providing and or them together.

C probably could have put & and * at the same level and | and + on the
same level (with ^ in between) to meat this need, but there may have
been some common usage that made it better to put them where they are as
a distinct set of levels.

[toc] | [prev] | [next] | [standalone]


#141937

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2019-03-13 09:26 -0700
Message-ID<86wol2rb9o.fsf@mailhub.linuxsc.com>
In reply to#141858
Richard Damon <Richard@Damon-Family.org> writes:

> C probably could have put & and * at the same level and | and + on
> the same level (with ^ in between) to meat this need, but there
> may have been some common usage that made it better to put them
> where they are as a distinct set of levels.

I thought it was well known that early C didn't have && and ||,
so the bitwise operators &, ^, and | were put below the
comparison operators so they could be used as logical connectives.

[toc] | [prev] | [next] | [standalone]


#141938

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2019-03-13 10:11 -0700
Message-ID<86sgvqr96y.fsf@mailhub.linuxsc.com>
In reply to#141847
Joe Pfeiffer <pfeiffer@cs.nmsu.edu> writes:

> By the time you've got 15 levels for 49 operators, any sane
> programmer will be putting in some extra parentheses here and
> there

Sure, if there is no particular structure to the levels and
which operators go where.  In C there is quite a bit of
structure (and at the risk of repeating myself, there are
better ways to indicate grouping than using parentheses).

> [...], and if I don't remember for sure in my own code

It isn't hard to remember if one makes an effort to learn.
Fifteen to thiry minutes, tops, and that's a one-time cost.

> it probably isn't fair to expect someone coming along later
> (possibly even me under a full moon) to have the same intuition.

This is a circular pattern.  We expect people won't remember, and
because they aren't expected to learn and remember they don't learn
and remember, and since they don't we have low expectations...
and the cycle continues.  We should reverse the direction of the
cycle.

[toc] | [prev] | [next] | [standalone]


#141939

FromBart <bc@freeuk.com>
Date2019-03-13 17:40 +0000
Message-ID<mgbiE.394290$Apg.172496@fx36.am4>
In reply to#141938
On 13/03/2019 17:11, Tim Rentsch wrote:
> Joe Pfeiffer <pfeiffer@cs.nmsu.edu> writes:
> 
>> By the time you've got 15 levels for 49 operators, any sane
>> programmer will be putting in some extra parentheses here and
>> there
> 
> Sure, if there is no particular structure to the levels and
> which operators go where.  In C there is quite a bit of
> structure (and at the risk of repeating myself, there are
> better ways to indicate grouping than using parentheses).
> 
>> [...], and if I don't remember for sure in my own code
> 
> It isn't hard to remember if one makes an effort to learn.
> Fifteen to thiry minutes, tops, and that's a one-time cost.
> 
>> it probably isn't fair to expect someone coming along later
>> (possibly even me under a full moon) to have the same intuition.
> 
> This is a circular pattern.  We expect people won't remember, and
> because they aren't expected to learn and remember they don't learn
> and remember, and since they don't we have low expectations...
> and the cycle continues.  We should reverse the direction of the
> cycle.
> 

People want to write code so that it is clear to everyone else. 
Including those more used to other languages which have different 
precedences.

There is NO advantage to writing expressions whose meanings are 
critically dependent on the relative precedences of &, | and ^.

Plus, many operators just have the wrong precedence, so you want to 
employ them in the most natural manner. And that requires parentheses.

Which, as a bonus, makes code more portable.

[toc] | [prev] | [next] | [standalone]


#141944

FromKeith Thompson <kst-u@mib.org>
Date2019-03-13 15:24 -0700
Message-ID<lnwol2jtu7.fsf@kst-u.example.com>
In reply to#141939
Bart <bc@freeuk.com> writes:
[...]
> People want to write code so that it is clear to everyone else. 
> Including those more used to other languages which have different 
> precedences.
>
> There is NO advantage to writing expressions whose meanings are 
> critically dependent on the relative precedences of &, | and ^.
>
> Plus, many operators just have the wrong precedence, so you want to 
> employ them in the most natural manner. And that requires parentheses.

I mostly agree.  I suspect we'd differ about how much readers can
reasonably be expected to know, but let's not get into that.

> Which, as a bonus, makes code more portable.

In what sense is it more portable?  If I write C code that depends
on all 15 precedence levels, it's likely to be difficult for
human readers to understand it, but every C compiler will parse
it correctly.  I've never heard of a C compiler having an operator
precedence bug.  It's just too easy to get it right.

If you mean "portable" in the sense that it's easier to translate
to a different language, that's hardly ever worth worrying about.
(And a lot of languages uses the same precedence levels as C.)

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Will write code for food.
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#141945

FromBart <bc@freeuk.com>
Date2019-03-13 23:43 +0000
Message-ID<YAgiE.62819$Vy.42137@fx39.am4>
In reply to#141944
On 13/03/2019 22:24, Keith Thompson wrote:
> Bart <bc@freeuk.com> writes:
> [...]
>> People want to write code so that it is clear to everyone else.
>> Including those more used to other languages which have different
>> precedences.
>>
>> There is NO advantage to writing expressions whose meanings are
>> critically dependent on the relative precedences of &, | and ^.
>>
>> Plus, many operators just have the wrong precedence, so you want to
>> employ them in the most natural manner. And that requires parentheses.
> 
> I mostly agree.  I suspect we'd differ about how much readers can
> reasonably be expected to know, but let's not get into that.
> 
>> Which, as a bonus, makes code more portable.
> 
> In what sense is it more portable?  If I write C code that depends
> on all 15 precedence levels, it's likely to be difficult for
> human readers to understand it, but every C compiler will parse
> it correctly.  I've never heard of a C compiler having an operator
> precedence bug.  It's just too easy to get it right.
> 
> If you mean "portable" in the sense that it's easier to translate
> to a different language, that's hardly ever worth worrying about.

You've really never needed to write the same program in another 
language? (Was it you with that big list of the same program all in 
different languages or am I thinking of something else? I think 
fizzbuzz/whatever were all in C.)

> (And a lot of languages uses the same precedence levels as C.)

A lot do borrow from C, notable ones with links to the that language 
(derived from it, or people using C to implement theirs, as a target 
language etc).

But there is still a wide enough variation that you don't really want to 
rely on code relying on such a peculiar and unwieldy set of precedecdes:

https://rosettacode.org/wiki/Operator_precedence

[toc] | [prev] | [next] | [standalone]


#141946

FromKeith Thompson <kst-u@mib.org>
Date2019-03-13 17:43 -0700
Message-ID<lnsgvqjnex.fsf@kst-u.example.com>
In reply to#141945
Bart <bc@freeuk.com> writes:
> On 13/03/2019 22:24, Keith Thompson wrote:
[...]
>> If you mean "portable" in the sense that it's easier to translate
>> to a different language, that's hardly ever worth worrying about.
>
> You've really never needed to write the same program in another 
> language? (Was it you with that big list of the same program all in 
> different languages or am I thinking of something else? I think 
> fizzbuzz/whatever were all in C.)

I've hardly ever *needed* to.  (Yes, I've written FizzBuzz in 100
or so different langauges, but (a) that was purely for fun and
had no practical justification, and (b) most of the programs are
not translations.)

>> (And a lot of languages uses the same precedence levels as C.)
>
> A lot do borrow from C, notable ones with links to the that language 
> (derived from it, or people using C to implement theirs, as a target 
> language etc).
>
> But there is still a wide enough variation that you don't really want to 
> rely on code relying on such a peculiar and unwieldy set of precedecdes:
>
> https://rosettacode.org/wiki/Operator_precedence

There are valid reasons not to rely on too many precedence levels,
and to use parentheses for the benefit of the reader.  I just don't
think that the prospect of translating code from C to a different
language is one of them.

When I write C, I write C.  I don't expect anyone who doesn't know C to
be able to read and understand my code.  But I don't expect a typical C
programmer to know the relative precedences of bitwise and, or, and xor.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Will write code for food.
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#142037

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2019-03-18 08:53 -0700
Message-ID<86d0mop4a3.fsf@mailhub.linuxsc.com>
In reply to#141939
Bart <bc@freeuk.com> writes:

> On 13/03/2019 17:11, Tim Rentsch wrote:
>
>> Joe Pfeiffer <pfeiffer@cs.nmsu.edu> writes:
>>
>>> By the time you've got 15 levels for 49 operators, any sane
>>> programmer will be putting in some extra parentheses here and
>>> there
>>
>> Sure, if there is no particular structure to the levels and
>> which operators go where.  In C there is quite a bit of
>> structure (and at the risk of repeating myself, there are
>> better ways to indicate grouping than using parentheses).
>>
>>> [...], and if I don't remember for sure in my own code
>>
>> It isn't hard to remember if one makes an effort to learn.
>> Fifteen to thiry minutes, tops, and that's a one-time cost.
>>
>>> it probably isn't fair to expect someone coming along later
>>> (possibly even me under a full moon) to have the same intuition.
>>
>> This is a circular pattern.  We expect people won't remember, and
>> because they aren't expected to learn and remember they don't learn
>> and remember, and since they don't we have low expectations...
>> and the cycle continues.  We should reverse the direction of the
>> cycle.
>
> People want to write code so that it is clear to everyone
> else.  Including those more used to other languages which have
> different precedences.  [...]

Yes, some people have all sorts of idiotic ideas.  They are
welcome to think what they like, as long as they don't try
to force their ideas on people who don't want them.

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | comp.lang.c


csiph-web