Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

C precedence - relative comparisons before equality operators

87 views
Skip to first unread message

James Harris

unread,
Sep 5, 2021, 1:49:49 PM9/5/21
to
According to

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

and other references C applies relative comparisons (<, <=, >=, >)
before equality comparisons (==, !=) rather than giving them all the
same priority.

Anyone know why the precedences were designed that way?

Are there certain idioms in which that arrangement is useful?


--
James Harris

Siri Cruise

unread,
Sep 5, 2021, 4:12:12 PM9/5/21
to
In article <sh2vvh$oir$1...@dont-email.me>,
James Harris <james.h...@gmail.com> wrote:

> According to
>
> https://en.cppreference.com/w/c/language/operator_precedence
>
> and other references C applies relative comparisons (<, <=, >=, >)
> before equality comparisons (==, !=) rather than giving them all the
> same priority.

== serves as scalar equality and logical equivalence.

Parentheses are easy to type.

--
:-<> Siri Seal of Disavowal #000-001. Disavowed. Denied. Deleted. @
'I desire mercy, not sacrifice.' /|\
Discordia: not just a religion but also a parody. This post / \
I am an Andrea Doria sockpuppet. insults Islam. Mohammed

Ben Bacarisse

unread,
Sep 5, 2021, 4:13:02 PM9/5/21
to
I'm curious now too. I don't know of any, but then I've not see a
particularly large quantity of C code.

There is one that uses arithmetic between comparisons to get a -1, 0, +1
result where such a thing is required:

(a >= b) - (b >= a)

but that, of course, /needs/ the parentheses.

As to why it's like this, I suspect that DMR just liked lots of
precedence levels to avoid ()s in as many cases as possible. If you do
decide to separate the groups, one has to be higher than the other and,
though not common or idiomatic, equality and non-equality of comparisons
seem to make more sense than comparisons of equality and non-equality.

--
Ben.

Kenny McCormack

unread,
Sep 5, 2021, 4:19:45 PM9/5/21
to
In article <sh2vvh$oir$1...@dont-email.me>,
James Harris <james.h...@gmail.com> wrote:
I think it makes sense. If I see:

if (a < b == c < d)

I would expect it to mean:

if ((a < b) == (c < d))

That's got to be more useful than:

if ((a < (b == c)) < d)

--
You know politics has really been turned upside down when you have someone in the
government with a last name of Cheney (Liz, Senator from Wyoming) who is the voice of
reason.

Richard Damon

unread,
Sep 5, 2021, 5:53:02 PM9/5/21
to
On 9/5/21 4:19 PM, Kenny McCormack wrote:
> In article <sh2vvh$oir$1...@dont-email.me>,
> James Harris <james.h...@gmail.com> wrote:
>> According to
>>
>> https://en.cppreference.com/w/c/language/operator_precedence
>>
>> and other references C applies relative comparisons (<, <=, >=, >)
>> before equality comparisons (==, !=) rather than giving them all the
>> same priority.
>>
>> Anyone know why the precedences were designed that way?
>>
>> Are there certain idioms in which that arrangement is useful?
>
> I think it makes sense. If I see:
>
> if (a < b == c < d)
>
> I would expect it to mean:
>
> if ((a < b) == (c < d))
>
> That's got to be more useful than:
>
> if ((a < (b == c)) < d)
>

I think that is probably about as good of an arguement as any will find.

Since the grammer doesn't easily support what some later langagues did
to make a < b < c to mean (a < b) && (b < c) which can be handy being
able to say something like a < b == b < c at least lets you test if 3
numbers are in sequence without parenthesis.

Also, it puts less operators at any give level of the grammer which
might be useful. You end up with more levels of grammer, but each one is
simpler.

Bart

unread,
Sep 5, 2021, 7:10:11 PM9/5/21
to
On 05/09/2021 22:52, Richard Damon wrote:
> On 9/5/21 4:19 PM, Kenny McCormack wrote:
>> In article <sh2vvh$oir$1...@dont-email.me>,
>> James Harris <james.h...@gmail.com> wrote:
>>> According to
>>>
>>> https://en.cppreference.com/w/c/language/operator_precedence
>>>
>>> and other references C applies relative comparisons (<, <=, >=, >)
>>> before equality comparisons (==, !=) rather than giving them all the
>>> same priority.
>>>
>>> Anyone know why the precedences were designed that way?
>>>
>>> Are there certain idioms in which that arrangement is useful?
>>
>> I think it makes sense. If I see:
>>
>> if (a < b == c < d)
>>
>> I would expect it to mean:
>>
>> if ((a < b) == (c < d))
>>
>> That's got to be more useful than:
>>
>> if ((a < (b == c)) < d)
>>
>
> I think that is probably about as good of an arguement as any will find.

I think given some of the other crazy decisions, it's probably
accidental if this particular one has any benefit.

>
> Since the grammer doesn't easily support what some later langagues did
> to make a < b < c to mean (a < b) && (b < c) which can be handy being
> able to say something like a < b == b < c at least lets you test if 3
> numbers are in sequence without parenthesis.

In sequence maybe, but it doesn't distinguish between ascending or
descending as a < b < c would do in properly chained comparisons.

I think the OP is thinking of implementing chained comparisons, and may
be gauging what would be lost if moving away from the C model.

Personally I wouldn't care about that; Python has chained comparisons so
it doesn't care about compatibility with C expressions either.

(I have them too, but I can emulate whatever C does by adding parentheses.)



> Also, it puts less operators at any give level of the grammer which
> might be useful. You end up with more levels of grammer, but each one is
> simpler.

I dispute it's that useful; but it is certainly harder to remember all
the different levels. You can also can't assume that everyone will know
them as well as you.

Ben Bacarisse

unread,
Sep 5, 2021, 9:01:40 PM9/5/21
to
r...@zedat.fu-berlin.de (Stefan Ram) writes:

> James Harris <james.h...@gmail.com> writes:
>>Anyone know why the precedences were designed that way?
>
> The precedence of > < <= >= over == != was already
> present in B.

Ah. But not in BCPL, so Thompson thought it worth splitting them.

Mind you, BCPL permits expressions like a < b < c and a < b = 0 with
the usual "mathematical" meaning.

--
Ben.

David Brown

unread,
Sep 6, 2021, 3:09:27 AM9/6/21
to
The relational operators and equality operators can be applied to
different things (there are more possibilities for equality comparison).
I guess that meant it made sense to consider them as separate operator
groups. And since each group has to fit at a different spot in the list
of precedences, it was either relational operators before equality
operators, or vice versa.

David Brown

unread,
Sep 6, 2021, 3:15:42 AM9/6/21
to
I think that is a very likely reason.

>
> I dispute it's that useful; but it is certainly harder to remember all
> the different levels. You can also can't assume that everyone will know
> them as well as you.

You don't need to remember all the different levels. You need to
remember the common ones, and they are all pretty obvious - no one is
going to be in doubt about the meaning of "a = b * c + d;".

Beyond that, you can always add parenthesis or split the expression into
sub-expressions - whatever makes the code clearer and more maintainable.

You might need to be able to understand other people's code written with
fewer parenthesis than you might personally like, but usually it's clear
what they meant unless they were deliberately writing smart-arse code.


James Harris

unread,
Sep 6, 2021, 4:27:29 AM9/6/21
to
On 05/09/2021 23:29, Stefan Ram wrote:
> James Harris <james.h...@gmail.com> writes:
>> Anyone know why the precedences were designed that way?
>
> The precedence of > < <= >= over == != was already
> present in B.

Was that in just some versions of B? It looks as though relational and
equality comparisons are at the same level in

https://www.thinkage.ca/gcos/expl/b/manu/manu.html#AppendixB

Of course, that may not be right but I wonder if Thompson changed from
one set of precedence levels to the other, and why.

>
> Kernighan/Ritchie wrote:
>
> |The == (equal to) and the != (not equal to) operators are
> |analogous to the relational operators except for their lower
> |precedence. (Thus a<b == c<d is 1 whenever a<b and c<d have
> |the same truth-value.)

Do you have a link to the source of that?


--
James Harris

James Harris

unread,
Sep 6, 2021, 4:40:01 AM9/6/21
to
I guess that's the meaning of "The result of evaluating an extended
relation is true if and only if all the individual relations are true." in

https://www.bell-labs.com/usr/dmr/www/bcpl.pdf

That document also appears to back up what you say about relative
precedences. It says "The relational operators are less binding than the
arithmetic operators."

And, subsequently, "the shift operators are less binding than the
relations on the left and more binding on the right." - which means
something or other...!


--
James Harris

Ben Bacarisse

unread,
Sep 6, 2021, 5:46:53 AM9/6/21
to
James Harris <james.h...@gmail.com> writes:

> On 06/09/2021 02:01, Ben Bacarisse wrote:
>> r...@zedat.fu-berlin.de (Stefan Ram) writes:
>>
>>> James Harris <james.h...@gmail.com> writes:
>>>> Anyone know why the precedences were designed that way?
>>>
>>> The precedence of > < <= >= over == != was already
>>> present in B.
>>
>> Ah. But not in BCPL, so Thompson thought it worth splitting them.
>> Mind you, BCPL permits expressions like a < b < c and a < b = 0 with
>> the usual "mathematical" meaning.
>
> I guess that's the meaning of "The result of evaluating an extended
> relation is true if and only if all the individual relations are
> true." in
>
> https://www.bell-labs.com/usr/dmr/www/bcpl.pdf

Later documents are much clearer on this point. The above document is
a technical note and not really a user manual.

> That document also appears to back up what you say about relative
> precedences. It says "The relational operators are less binding than
> the arithmetic operators."
>
> And, subsequently, "the shift operators are less binding than the
> relations on the left and more binding on the right." - which means
> something or other...!

It was trendy to have asymmetric precedence at one time (exponentiation
was the most common example, I think), but that seems to have been
dropped in later manuals.

--
Ben.

Bart

unread,
Sep 6, 2021, 6:10:24 AM9/6/21
to
If everybody was trusted to do that, or expected to, then what was the
point of having so many precedence levels?!

(How many can list the precedence levels of &, | and ^, or can explain
why any one is ranked higher than another?)

C has twice as many as I do for the same set of operators.

Specifically, I parse a<<8 + b the same way as a*256 + b, for obvious
reasons. In C, one is a<<(8+b), the other is (a*256)+b.


David Brown

unread,
Sep 6, 2021, 7:01:55 AM9/6/21
to
On 06/09/2021 12:10, Bart wrote:
> On 06/09/2021 08:15, David Brown wrote:
>> On 06/09/2021 01:09, Bart wrote:
>>> On 05/09/2021 22:52, Richard Damon wrote:
>>>
>>>> Also, it puts less operators at any give level of the grammer which
>>>> might be useful. You end up with more levels of grammer, but each
>>>> one is
>>>> simpler.
>>
>> I think that is a very likely reason.
>>
>>>
>>> I dispute it's that useful; but it is certainly harder to remember all
>>> the different levels. You can also can't assume that everyone will know
>>> them as well as you.
>>
>> You don't need to remember all the different levels.  You need to
>> remember the common ones, and they are all pretty obvious - no one is
>> going to be in doubt about the meaning of "a = b * c + d;".
>>
>> Beyond that, you can always add parenthesis or split the expression into
>> sub-expressions - whatever makes the code clearer and more maintainable.
>>
>> You might need to be able to understand other people's code written with
>> fewer parenthesis than you might personally like, but usually it's clear
>> what they meant unless they were deliberately writing smart-arse code.
>
> If everybody was trusted to do that, or expected to, then what was the
> point of having so many precedence levels?!

As has been discussed, it simplifies the grammar and language
specification if operators are divided into groups based on the type of
operands allowed, and then having these groups given different precedence.

>
> (How many can list the precedence levels of &, | and ^, or can explain
> why any one is ranked higher than another?)

For "and" and "or" operations, it is standard mathematical convention to
treat "and" as higher precedence than "or". The operations are even
written as "." and "+" in many cases. Where exclusive or fits in is a
different matter.

>
> C has twice as many as I do for the same set of operators.
>

Do you actually have a formal grammar and language specification?

> Specifically, I parse a<<8 + b the same way as a*256 + b, for obvious
> reasons. In C, one is a<<(8+b), the other is (a*256)+b.
>

I assume you are thinking of shifts as a kind of multiplication or
division, and therefore it should be a higher precedence than addition
and subtraction. Looking at things purely objectively, I'd be inclined
to agree. I am generous with parenthesis when using shift operators.


James Harris

unread,
Sep 6, 2021, 7:18:23 AM9/6/21
to
On 06/09/2021 09:27, James Harris wrote:
> On 05/09/2021 23:29, Stefan Ram wrote:

...

>>    Kernighan/Ritchie wrote:
>>
>> |The == (equal to) and the != (not equal to) operators are
>> |analogous to the relational operators except for their lower
>> |precedence. (Thus a<b == c<d is 1 whenever a<b and c<d have
>> |the same truth-value.)
>
> Do you have a link to the source of that?

No need to reply. I found it in A.7.10 of

https://osm.hpi.de/bs/2019/material/The_C_Programming_Language.pdf


--
James Harris

Malcolm McLean

unread,
Sep 6, 2021, 7:21:02 AM9/6/21
to
On Monday, 6 September 2021 at 12:01:55 UTC+1, David Brown wrote:
>
> > (How many can list the precedence levels of &, | and ^, or can explain
> > why any one is ranked higher than another?)
> For "and" and "or" operations, it is standard mathematical convention to
> treat "and" as higher precedence than "or". The operations are even
> written as "." and "+" in many cases. Where exclusive or fits in is a
> different matter.
>
And is similar to multiplication. If half of the children are boys and a third
have ice creams, then the number who are boys and have ice creams should
be 1/2 * 1/3 = 1/6.
Or is similar to addition. If 1 in ten thousand have the dreaded lurgy, and 1
in ten thousand are hypochondriacs who think they have the dreaded lurgy,
the proportion of people in your clinic will be 1/10000 + 1/10000 =
1/5000 (the number of hypochondriacs with genuine dreaded lurgy is
so small it can be ignored).

David Brown

unread,
Sep 6, 2021, 7:45:03 AM9/6/21
to
On 06/09/2021 13:18, James Harris wrote:
> On 06/09/2021 09:27, James Harris wrote:
>> On 05/09/2021 23:29, Stefan Ram wrote:
>
> ...
>
>>>    Kernighan/Ritchie wrote:
>>>
>>> |The == (equal to) and the != (not equal to) operators are
>>> |analogous to the relational operators except for their lower
>>> |precedence. (Thus a<b == c<d is 1 whenever a<b and c<d have
>>> |the same truth-value.)
>>
>> Do you have a link to the source of that?
>
> No need to reply. I found it in A.7.10 of
>

Please do not post links to copyrighted books. I don't know if that
link is legal or a copyright violation, but "some link I found with
google" is certainly inappropriate.

It is also long out of date - TCPL is historically interesting, and a
fine example of good technical writing, but not necessarily an accurate
reference of current C - it formed the basis of the C standard, but has
not been updated with the standard.

The current C standard is C17, with the last pre-certification draft
available freely and legally from the WG14 themselves at:

<http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2176.pdf>


C99, C11 and the latest draft of C2x are also available:

<http://www.open-std.org/jtc1/sc22/wg14/www/projects>

(You'll find the text in question in 6.5.8p8 and footnote 110).

James Harris

unread,
Sep 6, 2021, 8:38:43 AM9/6/21
to
On 06/09/2021 12:44, David Brown wrote:
> On 06/09/2021 13:18, James Harris wrote:
>> On 06/09/2021 09:27, James Harris wrote:
>>> On 05/09/2021 23:29, Stefan Ram wrote:
>>
>> ...
>>
>>>>    Kernighan/Ritchie wrote:
>>>>
>>>> |The == (equal to) and the != (not equal to) operators are
>>>> |analogous to the relational operators except for their lower
>>>> |precedence. (Thus a<b == c<d is 1 whenever a<b and c<d have
>>>> |the same truth-value.)
>>>
>>> Do you have a link to the source of that?
>>
>> No need to reply. I found it in A.7.10 of
>>
>
> Please do not post links to copyrighted books. I don't know if that
> link is legal or a copyright violation, but "some link I found with
> google" is certainly inappropriate.

Not so. The book is published on the website of the Hasso Plattner
Institute in Germany. You can read about them at

https://en.wikipedia.org/wiki/Hasso_Plattner_Institute

I checked before posting the link that they were legitimate. As such,
they have to take responsibility for what they publish and may well have
(or, will likely have) permission to do so, especially if they have had
the book on their website since 2019, as appears to be the case.

>
> It is also long out of date - TCPL is historically interesting, and a
> fine example of good technical writing, but not necessarily an accurate
> reference of current C - it formed the basis of the C standard, but has
> not been updated with the standard.

I was asking for the source of the quote. Therefore the older the
reference the better.


>
> The current C standard is C17, with the last pre-certification draft
> available freely and legally from the WG14 themselves at:
>
> <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2176.pdf>
>
>
> C99, C11 and the latest draft of C2x are also available:
>
> <http://www.open-std.org/jtc1/sc22/wg14/www/projects>
>
> (You'll find the text in question in 6.5.8p8 and footnote 110).
>

Thanks. Yes, I found the quote in a draft standard before I found the
K&R2 version. It's surprising that it was so little changed.


--
James Harris

Ben Bacarisse

unread,
Sep 6, 2021, 8:44:59 AM9/6/21
to
James Harris <james.h...@gmail.com> writes:

> On 05/09/2021 23:29, Stefan Ram wrote:
>> James Harris <james.h...@gmail.com> writes:
>>> Anyone know why the precedences were designed that way?
>> The precedence of > < <= >= over == != was already
>> present in B.
>
> Was that in just some versions of B? It looks as though relational and
> equality comparisons are at the same level in
>
> https://www.thinkage.ca/gcos/expl/b/manu/manu.html#AppendixB
>
> Of course, that may not be right but I wonder if Thompson changed from
> one set of precedence levels to the other, and why.

Strange. The GCOS version was the only one I ever used, but I have no
memory of the operator precedence.

>> Kernighan/Ritchie wrote:
>> |The == (equal to) and the != (not equal to) operators are
>> |analogous to the relational operators except for their lower
>> |precedence. (Thus a<b == c<d is 1 whenever a<b and c<d have
>> |the same truth-value.)
>
> Do you have a link to the source of that?

It's from the C book (K&R). Section 7.7 190, page 190 in the 1st edition.

--
Ben.

Richard Damon

unread,
Sep 6, 2021, 10:09:55 AM9/6/21
to
On 9/6/21 5:46 AM, Ben Bacarisse wrote:
> It was trendy to have asymmetric precedence at one time (exponentiation
> was the most common example, I think), but that seems to have been
> dropped in later manuals.

When "Operator precedence" isn't described in terms of actual operator
precedence, but a grammar production rule, it is easy to create the
asymmetric cases.

I wonder if the issue is that more modern systems go to a less grammar
and more descriptive way to describe expressions, which makes this sort
of asymmetry harder to describe and thus undesirable.

It may also be related to how we write parsers, a grammar based parser
will tend to be bigger, as you need separate code (at least somewhat)
for each level of the grammar, while a precedence based parser while
somewhat more complicated that a single grammar rule, is smaller as the
repetition of rules becomes a table of operators and precedence.

Ben Bacarisse

unread,
Sep 6, 2021, 11:05:46 AM9/6/21
to
The "usual" expression parser can handle asymmetric cases just fine.
You pass in the precedence (starting with, say, 0) and the parse is
driven by a table giving associativity along with left and right
precedences to pass down when parsing sub-expressions.

I suspect tools like yacc might have played a role in its dying out.
While you can write a suitable grammar in yacc, it also has a built in
way to parse expressions simply by giving one precedence.

--
Ben.

David Brown

unread,
Sep 6, 2021, 12:12:25 PM9/6/21
to
On 06/09/2021 14:38, James Harris wrote:
> On 06/09/2021 12:44, David Brown wrote:
>> On 06/09/2021 13:18, James Harris wrote:
>>> On 06/09/2021 09:27, James Harris wrote:
>>>> On 05/09/2021 23:29, Stefan Ram wrote:
>>>
>>> ...
>>>
>>>>>     Kernighan/Ritchie wrote:
>>>>>
>>>>> |The == (equal to) and the != (not equal to) operators are
>>>>> |analogous to the relational operators except for their lower
>>>>> |precedence. (Thus a<b == c<d is 1 whenever a<b and c<d have
>>>>> |the same truth-value.)
>>>>
>>>> Do you have a link to the source of that?
>>>
>>> No need to reply. I found it in A.7.10 of
>>>
>>
>> Please do not post links to copyrighted books.  I don't know if that
>> link is legal or a copyright violation, but "some link I found with
>> google" is certainly inappropriate.
>
> Not so. The book is published on the website of the Hasso Plattner
> Institute in Germany. You can read about them at
>
>   https://en.wikipedia.org/wiki/Hasso_Plattner_Institute
>
> I checked before posting the link that they were legitimate.

They are a "real" institution, connected to a university, according to
Wikipedia.

> As such,
> they have to take responsibility for what they publish and may well have
> (or, will likely have) permission to do so, especially if they have had
> the book on their website since 2019, as appears to be the case.
>

They could quite easily have got this wrong, or someone has published
the book on their site without going through the proper checks and
controls. It is perhaps unlikely that someone would knowingly and
intentionally violate copyright with a link on the site, but mistakes
happen.

Assuming (and I'll assume that, until shown otherwise) they don't have
rights to publish the book, then they should not have done so. However,
that does not give /you/ the right to publish the link. It means you
are both wrong, and both failed to make appropriate checks for a book
that is so clearly and obviously copyrighted.

>>
>> It is also long out of date - TCPL is historically interesting, and a
>> fine example of good technical writing, but not necessarily an accurate
>> reference of current C - it formed the basis of the C standard, but has
>> not been updated with the standard.
>
> I was asking for the source of the quote. Therefore the older the
> reference the better.
>

A page number in the book would be a good reference. A link to a
questionable (at best) copy of the book is not.

>
>>
>> The current C standard is C17, with the last pre-certification draft
>> available freely and legally from the WG14 themselves at:
>>
>> <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2176.pdf>
>>
>>
>> C99, C11 and the latest draft of C2x are also available:
>>
>> <http://www.open-std.org/jtc1/sc22/wg14/www/projects>
>>
>> (You'll find the text in question in 6.5.8p8 and footnote 110).
>>
>
> Thanks. Yes, I found the quote in a draft standard before I found the
> K&R2 version. It's surprising that it was so little changed.
>

Not really - changing as little as possible is the hallmark of C.

tth

unread,
Sep 6, 2021, 12:20:32 PM9/6/21
to
On 9/6/21 1:44 PM, David Brown wrote:

> The current C standard is C17, with the last pre-certification draft
> available freely and legally from the WG14 themselves at:
>
> <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2176.pdf>
>

Enter the password to open this PDF file.
[Cancel] [OK]


--
+-------------------------------------------------------------------+
| sphinx of black quartz, judge my vow. |
+-------------------------------------------------------------------+

David Brown

unread,
Sep 6, 2021, 5:40:44 PM9/6/21
to
On 06/09/2021 18:20, tth wrote:
> On 9/6/21 1:44 PM, David Brown wrote:
>
>> The current C standard is C17, with the last pre-certification draft
>> available freely and legally from the WG14 themselves at:
>>
>> <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2176.pdf>
>>
>
>          Enter the password to open this PDF file.
>                     [Cancel]   [OK]
>

Odd.

You can get it from the link here :
<https://www.iso-9899.info/wiki/The_Standard>

Certainly they did publish it freely, without any protection. (That is
why I think it is fine to publish a link to it - you can also get the
same link from the Wikipedia article.) The links from the WG14 project
page <http://www.open-std.org/jtc1/sc22/wg14/www/projects> cover other
draft standards without protection, but the C17 link currently has an
early C2x draft rather than a late C17 draft.

Keith Thompson

unread,
Sep 6, 2021, 8:21:04 PM9/6/21
to
James Harris <james.h...@gmail.com> writes:
> On 06/09/2021 09:27, James Harris wrote:
>> On 05/09/2021 23:29, Stefan Ram wrote:
> ...
>
>>>    Kernighan/Ritchie wrote:
>>>
>>> |The == (equal to) and the != (not equal to) operators are
>>> |analogous to the relational operators except for their lower
>>> |precedence. (Thus a<b == c<d is 1 whenever a<b and c<d have
>>> |the same truth-value.)
>> Do you have a link to the source of that?
>
> No need to reply. I found it in A.7.10 of
>
> https://[SNIP]/The_C_Programming_Language.pdf

That is almost certainly a pirated copy of K&R2, uploaded by an
individual at the institution who either did not know or did not care
that it's a copyright violation. (Let's not have an argument about
whether "pirated" is the appropriate word, please.)

My paper copy of that book has a copyright notice just before the table
of contents. It was omitted from the PDF, I presume deliberately.

If Bell Labs or Prentice Hall had ever given permission for K&R2 to be
freely published, I'm sure someone here would have heard about it.

Legitimate copies of K&R2 are available from various vendors, as are
used copies of K&R1 for those who are interested in the historical
context.

--
Keith Thompson (The_Other_Keith) Keith.S.T...@gmail.com
Working, but not speaking, for Philips
void Void(void) { Void(); } /* The recursive call of the void */

Keith Thompson

unread,
Sep 6, 2021, 8:23:36 PM9/6/21
to
James Harris <james.h...@gmail.com> writes:
> On 05/09/2021 23:29, Stefan Ram wrote:
>> James Harris <james.h...@gmail.com> writes:
>>> Anyone know why the precedences were designed that way?
>> The precedence of > < <= >= over == != was already
>> present in B.
>
> Was that in just some versions of B? It looks as though relational and
> equality comparisons are at the same level in
>
> https://www.thinkage.ca/gcos/expl/b/manu/manu.html#AppendixB
>
> Of course, that may not be right but I wonder if Thompson changed from
> one set of precedence levels to the other, and why.

https://www.bell-labs.com/usr/dmr/www/kbman.pdf

[...]

James Kuyper

unread,
Sep 6, 2021, 11:07:56 PM9/6/21
to
On 9/5/21 1:49 PM, James Harris wrote:
> According to
>
> https://en.cppreference.com/w/c/language/operator_precedence
>
> and other references C applies relative comparisons (<, <=, >=, >)
> before equality comparisons (==, !=) rather than giving them all the
> same priority.
>
> Anyone know why the precedences were designed that way?
>
> Are there certain idioms in which that arrangement is useful?

The "Rationale" is silent on this issue. Section 7.7 of K&R, 1st
edition, after describing the lower precedence of == and !=, mentions
that "Thus a<b == c<d is 1 whenever a<b and c<d have the same
truth-value." I wouldn't say that "a < b == c < d" qualifies as
idiomatic - but it is precisely the example I was planning to offer
before I checked what K&R said about the matter.
The key issue is not whether "a < b == c < d" is common, but only
whether it's significantly more common that "a == b < c == d", which
would be permitted if we reversed the precedences. The former is
something I can imagine writing under some rare circumstances, whereas
the latter is essentially equivalent to "a != b && c == d" (unless a or
b might be NaNs), which in my opinion is the clearer way to write such
an expression.

John Bode

unread,
Sep 7, 2021, 10:27:50 AM9/7/21
to
On 9/5/21 3:19 PM, Kenny McCormack wrote:
> In article <sh2vvh$oir$1...@dont-email.me>,
> James Harris <james.h...@gmail.com> wrote:
>> According to
>>
>> https://en.cppreference.com/w/c/language/operator_precedence
>>
>> and other references C applies relative comparisons (<, <=, >=, >)
>> before equality comparisons (==, !=) rather than giving them all the
>> same priority.
>>
>> Anyone know why the precedences were designed that way?
>>
>> Are there certain idioms in which that arrangement is useful?
>
> I think it makes sense. If I see:
>
> if (a < b == c < d)
>
> I would expect it to mean:
>
> if ((a < b) == (c < d))
>
> That's got to be more useful than:
>
> if ((a < (b == c)) < d)
>

That's exactly the example given in footnote 108 of N1570:

108) Because of the precedences, a<b == c<d is 1 whenever a<b and c<d
have the same truth-value

It's the same rationale as expecting "a + b == c + d" to be parsed as
"(a + b) == (c + d)". You want to see if two relational expressions
are equivalent, and the way to enable that without having to use
explicit parentheses everywhere is to make == and != lower precedence
than <, >, <=, and >=.

Bart

unread,
Sep 7, 2021, 7:20:24 PM9/7/21
to
But has anyone ever seen that in real code? And if they have, why
wouldn't they also, at some point, have seen:

(a == b) == (c == d)

Without parentheses, that becomes ((a==b)==c)==d).

It seems like they desperately wanted to find any excuse for justifying
an extra, gratuitous precedence level for everyone to remember, when
dropping one level would probably have had a greater net benefit.

John Bode

unread,
Sep 8, 2021, 3:18:34 PM9/8/21
to
As pointed out in another subthread, that split was already present in B
- Thompson decided it was worth doing for whatever reason. Perhaps he
hit the a<b == c<d case a lot more than most of us. Or maybe he just
though "hey, this could be useful".

C's expression grammar is set up to do mostly what you expect without
having to explicitly group operators and operands. "*p" works to
dereference a pointer object, and you can substitute "p" with any
postfix expression and it will still work as you expect - "*ap[i]",
"*fp()", "*s.p", etc. You don't have to write "*(ap[i])", "*(fp())",
etc.

Comparing the results of any two expressions is just a matter of
writing "expr == expr" or "expr != expr", and it works for almost
any expression - arithmetic, postfix, or relational.

You don't have to explicitly remember 16 levels of precedence; most of
the time you don't have to think about it at all. You only have to know
when the default precedence *doesn't* work for what you're trying to do.
0 new messages