• Re: Safety of casting from 'long' to 'int'

    From Keith Thompson@Keith.S.Thompson+u@gmail.com to comp.lang.c on Thu May 14 16:11:43 2026
    From Newsgroup: comp.lang.c

    Bart <bc@freeuk.com> writes:
    On 14/05/2026 01:59, Janis Papanagnou wrote:
    [...]
    (The point is that - with the exception of & ^ | - the ranking
    makes perfectly sense

    It doesn't make sense even then; here are the remaining groups for
    binary ops from high to low:

    (* / %) (+ -) (<< >>) (< <= >= >) (== !==) (&&) (||) (=)

    Why are the shift operators at that spot? This causes chaos in
    expressions like 'a << 3 + b' which are parsed as 'a << (3 + b)'.

    I've never heard anyone claim that C's operator precedence rules are
    ideal. They aren't. But they can't be changed without breaking
    existing code, so there's little point in complaining about it.

    Someone could probably make an argument that the existing precedences
    are more sensible than any alternatives, but that doesn't really
    matter.

    Why are == and != lower precedence than the other compare operators?
    In which circumstances would that be an advantage? This is just a
    pointless extra level, as such usage would be so unusual that you'd
    use parentheses anyway.

    I suggest that it doesn't matter why. It is what it is. And yes,
    I'd add parentheses in the unlikely event that I needed to write
    an expression that uses both equality and comparison operators
    (unless I were writing deliberately obfuscated code, which I've
    been known to do).

    TBF, while other languages may not have as many levels, they also have questionable choices, because there are no standards.

    Plenty of other languages have standards. I'm not aware of any
    correlation between whether a language has a written standard and
    how reasonable its operator precedence rules are.

    At best it is generally agreed that there are 3 groups (4 including assignment) again arranged from high to low:

    Agreed by whom?

    1 School arithmetic which everyone knows

    2 Comparisons

    3 Logical (and, or)

    4 (Assignment)

    These should be intuitive, all that's left is the ordering within
    group 1 and group 3, and also where these extra ops need to go:

    << >> & | ^

    In the case if C, it also decided that ?: belongs in this chart of
    /binary/ operators. (I supposed you can consider each of ? and : as a
    binary operator...)

    I don't know what chart you're referring to. There is no such chart
    in the C standard; the precedence is defined implicitly by the
    grammar rules. K&R2 Table 2.1 is a chart showing the precedence
    and associativity of C's operators. It includes unary, binary,
    and ternary operators.

    ?: is a ternary operator. It is not in any sense a binary operator.
    If you've seen a table that implies it's a binary operator, that
    table is wrong (or you've misinterpreted it).
    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@Keith.S.Thompson+u@gmail.com to comp.lang.c on Thu May 14 16:33:41 2026
    From Newsgroup: comp.lang.c

    cross@spitfire.i.gajendra.net (Dan Cross) writes:
    In article <86pl2yi0n3.fsf@linuxsc.com>,
    Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:
    [...]
    My main point is that "byte" and "octet" are talking about
    different kinds of things.

    Not really. It has always been understood to refer to the same
    kind of thing that "byte" refers to.

    I agree, at least for the way I understand the terms. For me,
    "octet" and "byte" refer to the same kind of thing. The difference
    is that an "octet" is specifically 8 bits, and a "byte" is a
    fundamental unit of storage for a given system (commonly 8 bits).
    ISO/IEC 2382 happens to agree with me.

    The problem was that, at the time the term "octet" was coined,
    the size of a byte (measured in bits) varied between different
    computers, and sometimes on the same computer. When people
    starting getting serious about making computers talk to one
    another, this became an issue: hence octet to have standard
    nomenclature.

    A computer might have 64k bytes of
    RAM, but normally I wouldn't (and I think normally other people
    wouldn't) say that a computer has 64k octets of RAM.

    Some would, though it may sound a bit odd.

    Agreed. "64k bytes" is certainly more common, but "64k octets"
    means essentially the same thing while being more specific.

    Also, the "k" suffix formally means 1000, but is often used to mean
    1024, which is why we have "Ki", "kibi" to denote a power of two
    explicitly.

    [...]]

    At this point, the term "byte" has been standardized by several
    different bodies (IEC, ISO) to be synonymous with octet. The
    continued use of "octet" by organizations like the IETF is
    mostly a legacy curiosity.

    Has it? The ISO C and C++ standards certainly do not use "byte"
    to mean exactly 8 bits. ISO/IEC 2382 says:

    byte

    string that consists of a number of bits, treated as a unit, and
    usually representing a character or a part of a character

    Note 1 to entry: The number of bits in a byte is fixed for a given
    data processing system.

    Note 2 to entry: The number of bits in a byte is usually 8.

    and

    octet

    8-bit byte

    byte that consists of eight bits

    <https://www.iso.org/obp/ui/#iso:std:iso-iec:2382:ed-1:v2:en>

    The latter implies that you can't have octets on a system with,
    say, 16-bit bytes, which doesn't match what I would have expected.
    I would think it would be reasonable to say that a system with
    16-bit bytes has, say, 32k bytes or 64k octets of memory. But C
    doesn't use the word "octet", so this is at best marginally topical.

    [...]
    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@Keith.S.Thompson+u@gmail.com to comp.lang.c on Thu May 14 16:40:02 2026
    From Newsgroup: comp.lang.c

    Bart <bc@freeuk.com> writes:
    [...]
    Unary operators aren't the problem. It's a mystery why they need to be
    in a table at all. Nobody's going to think that '&a + b' means '&(a +
    b)'.
    [...]

    It would be silly for an operator precedence tables to omit the
    operators that "everybody knows". If I had a table that didn't
    show *all* the operators, I'd look for a better table (like the
    one in K&R2).
    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@Keith.S.Thompson+u@gmail.com to comp.lang.c on Thu May 14 16:51:22 2026
    From Newsgroup: comp.lang.c

    Bart <bc@freeuk.com> writes:
    On 14/05/2026 03:58, Keith Thompson wrote:
    [...]
    With nested loops, "break" or "continue" always refers to the
    innermost loop. With a switch statement inside a loop, "break"
    refers to the switch statement, but "continue" refers to the loop.

    It's obviously not impossible to deal with, but I find it mildly
    annoying.

    Break doing the two jobs is a flaw. 'break' and 'continue' being
    inconsistent is a further one:

    Suppose you have a loop, and within the loop, you have an if-else-if
    chain within which are 'break' and 'continue' statements.

    You decide that that if-else-if chain is better off as a switch. But
    now, while 'continue' continues to do its job, 'break' silently
    behaves differently.

    Yes, that is a potential problem, one that could have been solved
    by not using "break" to terminate a case in a switch statement.
    I don't know that I've ever seen the scenario you describe, but
    it's certainly possible. I don't often use "continue", but yes,
    the asymmetry between "break" and "continue" is a potential problem.

    There is of course no real ambiguity, but it is a possible trap
    for the unwary.

    The problem could be largely solved by adding support for named break
    and continue, as I've discussed here before. That would also make it
    easier to break out of nested loops, even without switch statements.
    And it could be done without breaking existing code. (Making a
    break within a switch within a loop break out of the loop would
    change the behavior of existing code, so it's not likely to happen.)

    There, I've agreed with you (again) about a perceived flaw in
    the C language. Will you stop accusing me of defending it when I
    merely describe it? Or will you continue to be angry that I'm not
    as angry about it as you are?
    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@Keith.S.Thompson+u@gmail.com to comp.lang.c on Thu May 14 16:59:33 2026
    From Newsgroup: comp.lang.c

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    [...] the issue being discussed was that multiple cases (that may
    not be contiguous) depend on the default fallthrough behavior.

    case 10:
    case 20:
    case 30:
    whatever();
    break;

    In a hypothetical C-like language without default fallthrough, it
    would make sense to invent a different syntax. For C repeating the
    "case" keyword is slightly ugly, but probably not worth fixing.

    Both gcc and clang, with options -std=c99 -pedantic -Wall -Wextra,
    accept the code below and give no diagnostics:

    #include <stdio.h>
    #include "cases.h"

    int
    main( int argc, char *argv[] ){

    switch( argc-1 ){
    cases( 2, 3, 5, 8 ):

    [SNIP]

    The cases() macro is a fairly straightforward application of variadic
    macros, as follows:

    #define ARGS_N_(...) \
    ARGS_N_X_( __VA_ARGS__, \
    09, 08, 07, 06, 05, 04, 03, 02, 01, 00 \
    )

    #define ARGS_N_X_( dummy, _9, _8, _7, _6, _5, _4, _3, _2, _1, ... ) _1

    #define cases(...) casesx_( ARGS_N_( __VA_ARGS__ ), __VA_ARGS__ )
    #define casesx_( N, ... ) casesy_( N, __VA_ARGS__ )
    #define casesy_( N, ... ) cases_ ## N ## _( __VA_ARGS__ )

    #define cases_01_(a) case a
    #define cases_02_(a,...) case a : cases_01_( __VA_ARGS__ )
    #define cases_03_(a,...) case a : cases_02_( __VA_ARGS__ )
    #define cases_04_(a,...) case a : cases_03_( __VA_ARGS__ )
    #define cases_05_(a,...) case a : cases_04_( __VA_ARGS__ )
    #define cases_06_(a,...) case a : cases_05_( __VA_ARGS__ )
    #define cases_07_(a,...) case a : cases_06_( __VA_ARGS__ )
    #define cases_08_(a,...) case a : cases_07_( __VA_ARGS__ )
    #define cases_09_(a,...) case a : cases_08_( __VA_ARGS__ )

    It's easy to see how to extend this definition to allow more cases, if
    that is needed.

    Personally I would rather have something that works in C99, etc, now,
    than to wait for some possible change at some point in the indefinite
    future.

    Personally, I'd much rather just write:

    case 2: case 3: case 5: case 8:

    I find the default fallthrough behavior mildly annoying, but I don't
    have much problem dealing with it. I'm not willing to use elaborate
    macros to avoid it or to be able to write slightly terser code.
    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Bart@bc@freeuk.com to comp.lang.c on Fri May 15 01:12:12 2026
    From Newsgroup: comp.lang.c

    On 15/05/2026 00:11, Keith Thompson wrote:
    Bart <bc@freeuk.com> writes:
    On 14/05/2026 01:59, Janis Papanagnou wrote:
    [...]
    (The point is that - with the exception of & ^ | - the ranking
    makes perfectly sense

    It doesn't make sense even then; here are the remaining groups for
    binary ops from high to low:

    (* / %) (+ -) (<< >>) (< <= >= >) (== !==) (&&) (||) (=)

    Why are the shift operators at that spot? This causes chaos in
    expressions like 'a << 3 + b' which are parsed as 'a << (3 + b)'.

    I've never heard anyone claim that C's operator precedence rules are
    ideal. They aren't. But they can't be changed without breaking
    existing code, so there's little point in complaining about it.

    I was replying to the claim that they made 'perfect sense' aside from '&
    ^ |'

    TBF, while other languages may not have as many levels, they also have
    questionable choices, because there are no standards.

    Plenty of other languages have standards.

    I mean cross-language or real-world standards for operator precedences.

    There are de-facto ones for operators that everyone used like '* / + -',
    and also for '**' (exponentiation) even if that is an implied op in mathematical notation.

    In the computing world, logical 'add' before logical 'or' seems to be
    common.

    Those form groups 1 and 3 of my list below. Then common sense demands
    that comparisons must be group 2, otherwise:

    a + b == 0 might parsed as a + (b == 2)

    a == b && c == d might be parsed as a == (b && c) == d

    The fourth group is assignment. If that was any else other than the
    lowest level, then:

    a = b + c might be parsed as (a = b) + c
    a = b && c might be parsed as (a = b) && c
    a = b == c might be parsed as (a = b) == c

    depending on exactly where. None is desirable. In this case, C does the
    right thing anyway so no need to disagree!

    At best it is generally agreed that there are 3 groups (4 including
    assignment) again arranged from high to low:

    Agreed by whom?

    1 School arithmetic which everyone knows

    2 Comparisons

    3 Logical (and, or)

    4 (Assignment)

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.c on Fri May 15 02:30:33 2026
    From Newsgroup: comp.lang.c

    On 2026-05-15 01:11, Keith Thompson wrote:
    Bart <bc@freeuk.com> writes:

    Why are == and != lower precedence than the other compare operators?

    To prevent forcing parenthesis (which would make C-programs,
    which are already inherently overloaded with a plethora of (),
    {} and [], yet more unreadable).

    In which circumstances would that be an advantage? This is just a
    pointless extra level, as such usage would be so unusual that you'd
    use parentheses anyway.

    Equal and unequal are basically more universal operators than
    the other four types of value comparisons.[*] You can observe
    a hierarchy of types (reflected also in conditionals) where
    at the upper end you want a boolean predicate.

    bool x bool -> bool && and || arranged per logic convention
    type x type -> bool ==, !=, and then (see [*]) <, <=, >, >=
    type x type -> type various types including math convention

    And some specific cases in "C", like ++x and x++, which need
    some attention.

    Unaries are mostly not (or at least rarely) a problem. But...
    exponentiation needs attention, especially where unaries are
    involved in expressions. (Sadly there's differences here.)

    [*] I'm not considering that languages my impose an ordering in
    'boolean' values. As universal fundamental abstract type 'true'
    and 'false' are unordered and need no ordering. It makes sense
    to have classes more differentiated than thrown together and
    thereby requiring lots of parentheses to fix things again. It's
    a convenience based on common conventions and logical models.


    I suggest that it doesn't matter why. It is what it is. And yes,
    I'd add parentheses in the unlikely event that I needed to write
    an expression that uses both equality and comparison operators
    (unless I were writing deliberately obfuscated code, which I've
    been known to do).

    It's not "obfuscated", IMHO, if you have the conceptual model I
    presented in mind. But of course you could also use parenthesis
    to emphasize things, or use different spacing; I use all means
    depending on context and complexity of the expressions.

    [...]

    These should be intuitive, all that's left is the ordering within
    group 1 and group 3, and also where these extra ops need to go:

    << >> & | ^

    These are basically in the "value-operators" type x type -> type
    class, though the former two operators are asymmetric; they work
    like

    type1 x type2 -> type1

    so they are justified an own class.[**] It makes sense where "C"
    has them defined.

    [**] Yes, the arguments make technically both use of the same
    'int' type but they are semantically in different classes.

    The problem is with the latter three, & | ^ ; they are (typically)
    used with arithmetic value types, but they are sorted in after the
    comparison types.[***] - I cannot do anything about that and want
    to use parenthesis here, not (not primarily) for clarity, but to
    prevent computational errors in the first place.

    [***] Obviously the problem arose historically from using boolean
    operations through bit-sets occasionally as substitute for 'bool'.
    A misfortune of a coincidence of the language "flexibility" with
    its fuzziness of not separating 'bool' from 'int', and habits to
    use clever "optimized" coding. (I haven't seen such coding more
    recently, though, i.e. not during the past about four decades.
    I could imagine that it might play some role still in areas like controllers-programming, but don't know, to be frank.)

    Janis

    [...]
    [...]

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Bart@bc@freeuk.com to comp.lang.c on Fri May 15 01:31:59 2026
    From Newsgroup: comp.lang.c

    On 15/05/2026 00:40, Keith Thompson wrote:
    Bart <bc@freeuk.com> writes:
    [...]
    Unary operators aren't the problem. It's a mystery why they need to be
    in a table at all. Nobody's going to think that '&a + b' means '&(a +
    b)'.
    [...]

    It would be silly for an operator precedence tables to omit the
    operators that "everybody knows". If I had a table that didn't
    show *all* the operators, I'd look for a better table (like the
    one in K&R2).

    Do you need to know the precedence of a unary operator (say applied to
    any of these terms) in order to correctly parse this:

    a op1 b op2 c

    ?

    'a b c' are terms, and 'op1 op2' are operators. You need to know their relative precedences in order to correctly parse this as either '(a op1
    b) op2 c' or 'a op1 (b op2 c)'. Any unary ops on those terms don't
    affect that.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.c on Fri May 15 02:38:41 2026
    From Newsgroup: comp.lang.c

    On 2026-05-14 13:32, Bart wrote:
    On 14/05/2026 01:59, Janis Papanagnou wrote:
    [...]

    (The point is that - with the exception of & ^ | - the ranking
    makes perfectly sense

    It doesn't make sense even then; [...]

    I acknowledge that it doesn't make sense for you.

    (Some explanations can be found in a recent posting.)

    [...]

    TBF, while other languages may not have as many levels, they also have questionable choices, because there are no standards.

    There are common public conventions and conceptual models from the
    computer science that influence the definitions. Design constraints
    and goals of specific programming languages may influence details.
    Beyond that the languages generally define their precedence rules
    (and these are reflected in the respective language standards).

    [...]

    In the case if C, it also decided that ?: belongs in this chart of /
    binary/ operators. (I supposed you can consider each of ? and : as a
    binary operator...)

    (Here I'm sure you're imaging things or deliberately making them up.)

    Janis

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.c on Fri May 15 02:46:19 2026
    From Newsgroup: comp.lang.c

    On 2026-05-14 18:00, Bart wrote:
    On 14/05/2026 16:37, Tim Rentsch wrote:
    [...]
       1. unary operators are always ahead of binary operators, first
          those on the right and then those on the left;

    Unary operators aren't the problem. It's a mystery why they need to be
    in a table at all. [...]

    Well, they are; see for example these examples of Algol 68 and Awk...

    $ genie -p '-2^4'
    +16
    $ awk 'BEGIN {print -2^4}'
    -16


    Janis

    [...]

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@Keith.S.Thompson+u@gmail.com to comp.lang.c on Thu May 14 17:52:17 2026
    From Newsgroup: comp.lang.c

    Bart <bc@freeuk.com> writes:
    On 15/05/2026 00:40, Keith Thompson wrote:
    Bart <bc@freeuk.com> writes:
    [...]
    Unary operators aren't the problem. It's a mystery why they need to be
    in a table at all. Nobody's going to think that '&a + b' means '&(a +
    b)'.
    [...]
    It would be silly for an operator precedence tables to omit the
    operators that "everybody knows". If I had a table that didn't
    show *all* the operators, I'd look for a better table (like the
    one in K&R2).

    Do you need to know the precedence of a unary operator (say applied to
    any of these terms) in order to correctly parse this:

    a op1 b op2 c

    ?

    Perhaps not, though that's not an actual example. But that's not
    my point.

    'a b c' are terms, and 'op1 op2' are operators. You need to know their relative precedences in order to correctly parse this as either '(a
    op1 b) op2 c' or 'a op1 (b op2 c)'. Any unary ops on those terms don't
    affect that.

    Again, I see no point in having a C operator precedence
    table that doesn't include *all* the operators in the language.
    And I don't think I've ever seen such a table. It's much easier
    to include everything than to waste time deciding which operators
    don't need to be in the table.

    Has the presense of unary operators in a precedence table ever
    inconvenienced you in any way? Why is this a concern for you?

    If you want to publish a table that excludes unary operators,
    go ahead.
    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.c on Fri May 15 02:52:25 2026
    From Newsgroup: comp.lang.c

    On 2026-05-14 20:50, David Brown wrote:
    On 14/05/2026 20:19, Bart wrote:
    [...]

    I certainly agree it would be odd if there were binary arithmetic
    operators with higher precedence than unary operators.  [...]

    I've just posted an example; exponentiation. It depends on the
    language. (Below examples from Algol 68 and Awk...)

    $ genie -p '-2^4'
    +16
    $ awk 'BEGIN{print -2^4}'
    -16

    But (I think; unless that has changed) "C" has no exponentiation
    operator, so it doesn't apply here at least.

    But if you start with any new language you have to inspect the
    documentation about its operators and their precedence rules.

    Janis

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Bart@bc@freeuk.com to comp.lang.c on Fri May 15 02:07:35 2026
    From Newsgroup: comp.lang.c

    On 15/05/2026 01:52, Janis Papanagnou wrote:
    On 2026-05-14 20:50, David Brown wrote:
    On 14/05/2026 20:19, Bart wrote:
    [...]

    I certainly agree it would be odd if there were binary arithmetic
    operators with higher precedence than unary operators.  [...]

    I've just posted an example; exponentiation. It depends on the
    language. (Below examples from Algol 68 and Awk...)

    $ genie -p '-2^4'
                     +16
    $ awk 'BEGIN{print -2^4}'
    -16

    But (I think; unless that has changed) "C" has no exponentiation
    operator, so it doesn't apply here at least.

    But if you start with any new language you have to inspect the
    documentation about its operators and their precedence rules.


    Yes, negation with exponentation is a special case. Different languages produce different results. Getting the same result as in mathematics is tricky.

    It's not really helped by having having a table that combines
    precedences of different kinds of operator.

    And C gets off scot-free because it doesn't have such an operator. You
    can choose to write pow(-2, 4) or -pow(2, 4), with care taken as pow
    deals with floats.

    Other languages can also write (-2)**4 or -(2**4) to force the behaviour.

    But again, language syntax is not mathematics.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.c on Fri May 15 03:31:38 2026
    From Newsgroup: comp.lang.c

    On 2026-05-15 01:33, Keith Thompson wrote:
    cross@spitfire.i.gajendra.net (Dan Cross) writes:
    [...]

    At this point, the term "byte" has been standardized by several
    different bodies (IEC, ISO) to be synonymous with octet. The
    continued use of "octet" by organizations like the IETF is
    mostly a legacy curiosity.

    Has it? The ISO C and C++ standards certainly do not use "byte"
    to mean exactly 8 bits. ISO/IEC 2382 says:

    byte

    string that consists of a number of bits, treated as a unit, and
    usually representing a character or a part of a character

    Note 1 to entry: The number of bits in a byte is fixed for a given
    data processing system.

    Note 2 to entry: The number of bits in a byte is usually 8.

    and

    octet

    8-bit byte

    byte that consists of eight bits

    <https://www.iso.org/obp/ui/#iso:std:iso-iec:2382:ed-1:v2:en>

    The latter implies that you can't have octets on a system with,
    say, 16-bit bytes, which doesn't match what I would have expected.
    I would think it would be reasonable to say that a system with
    16-bit bytes has, say, 32k bytes or 64k octets of memory. But C
    doesn't use the word "octet", so this is at best marginally topical.

    I've seen octets used in ITU-T standards (called "recommendations")
    earlier than in ISO standards (who often borrowed ITU-T standards
    later under their label as an International Standard). Specifically
    in context of the ASN.1 definition in the 1980's (IIRC), specifically
    in ITU-T X.209 (which got later replaced by X.680, and X.690 for BER).
    I'm too lazy to "grep" the tons of the respective ITU-T papers, but
    Google(AI) confirms my memories when it says:

    | An octet, defined as a sequence of exactly 8 bits, is commonly
    | defined in several ITU-T (International Telecommunication Union -
    | Telecommunication Standardization Sector) standards, particularly
    | within the X-series for Open Systems Interconnection (OSI) and ASN.1
    | encoding.
    | Key ITU-T standards that define or rely on the definition| of an
    | octet include:
    | * ITU-T Rec. X.680 (ISO/IEC 8824-1): Defines the Abstract
    | Syntax Notation One (ASN.1) basic notation, where an "octet"
    | is fundamentally defined as an 8-bit unit.
    | * ...


    Janis

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.c on Fri May 15 03:39:20 2026
    From Newsgroup: comp.lang.c

    On 2026-05-15 03:07, Bart wrote:
    [...]

    It's not really helped by having having a table that combines
    precedences of different kinds of operator.

    It's a necessity to have precedences documented for the users.

    And tables are a very useful common, established representation;
    one can immediately see "who's first", yet more so to look up
    things if in doubt about any detail.

    If you're staying with your claim I cannot help you. Presumedly
    no one can help you. *sigh*

    Janis

    [...]
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.c on Fri May 15 03:51:02 2026
    From Newsgroup: comp.lang.c

    On 2026-05-14 12:08, David Brown wrote:

    Anyone curious about how far C's switch statements can be used or
    abused, might like to read about "Protothreads" :

    <https://en.wikipedia.org/wiki/Protothread>

    (I haven't yet read it.)

    This is a conglomeration of Duff's Device on steroids with supporting
    macros that gives you a limited type of stackless cooperative
    multitasking with extremely low overhead.  The library has seen real
    usage in small embedded systems.  Reactions to the underlying implementation range from thinking it is a hideous abuse of a bad
    language design, to elegant and very ingenious.

    Here we say "There's a fine line between genius and insanity."
    (The bandwidth of the reactions is thus not too astonishing.)

    Janis

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@cross@spitfire.i.gajendra.net (Dan Cross) to comp.lang.c on Fri May 15 01:56:51 2026
    From Newsgroup: comp.lang.c

    In article <10u5m4m$uo0d$3@kst.eternal-september.org>,
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote: >cross@spitfire.i.gajendra.net (Dan Cross) writes:
    In article <86pl2yi0n3.fsf@linuxsc.com>,
    Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:
    [...]
    My main point is that "byte" and "octet" are talking about
    different kinds of things.

    Not really. It has always been understood to refer to the same
    kind of thing that "byte" refers to.

    I agree, at least for the way I understand the terms. For me,
    "octet" and "byte" refer to the same kind of thing. The difference
    is that an "octet" is specifically 8 bits, and a "byte" is a
    fundamental unit of storage for a given system (commonly 8 bits).
    ISO/IEC 2382 happens to agree with me.

    Indeed; Werner Buchholz created the term "byte" while working on
    the IBM Stretch computer. This letter, from a 1977 issue of
    BYTE magazine (bit on the nose, honestly) claims it was 21 years
    old that year: https://archive.org/details/byte-magazine-1977-02/page/n145/mode/1up

    The letter says that initially, byte sizes ranged from 1 to 6
    bytes, but were extended to 8 bits in late 1956. The IBM 360
    used the same byte and word sizes as the Stretch, but fixed
    bytes at 8 bits.

    The problem was that, at the time the term "octet" was coined,
    the size of a byte (measured in bits) varied between different
    computers, and sometimes on the same computer. When people
    starting getting serious about making computers talk to one
    another, this became an issue: hence octet to have standard
    nomenclature.

    A computer might have 64k bytes of
    RAM, but normally I wouldn't (and I think normally other people
    wouldn't) say that a computer has 64k octets of RAM.

    Some would, though it may sound a bit odd.

    Agreed. "64k bytes" is certainly more common, but "64k octets"
    means essentially the same thing while being more specific.

    Yes. I understand that "octet" is preferred in French, enough
    so that I read it was the, "French word for byte." Not knowing
    French, I don't know if that's true.

    However, this cute story from Bob Bemer suggests he disliked the
    term "byte" and greaterly preferred "octet," pushing it when he
    was directly of software at Bull, in France, in the mid-1960s: https://web.archive.org/web/20170403130829/http://www.bobbemer.com/BYTE.HTM

    Also, the "k" suffix formally means 1000, but is often used to mean
    1024, which is why we have "Ki", "kibi" to denote a power of two
    explicitly.

    Yes. K, M, G, etc, have always been the SI indicators for
    powers of 10, not powers of 2. The "Ki", "Mi", "Gi", etc, forms
    are (as I understand it) relatively new.

    [...]]

    At this point, the term "byte" has been standardized by several
    different bodies (IEC, ISO) to be synonymous with octet. The
    continued use of "octet" by organizations like the IETF is
    mostly a legacy curiosity.

    Has it?

    Yes. IEC 80000-13 declares them to be synonyms.

    The ISO C and C++ standards certainly do not use "byte"
    to mean exactly 8 bits.

    Indeed. I don't blame them. I suspect there are some DSP chips
    or weird one-off processors with oddball byte sizes, even now.

    ISO/IEC 2382 says:

    byte

    string that consists of a number of bits, treated as a unit, and
    usually representing a character or a part of a character

    Note 1 to entry: The number of bits in a byte is fixed for a given
    data processing system.

    Note 2 to entry: The number of bits in a byte is usually 8.

    and

    octet

    8-bit byte

    byte that consists of eight bits

    <https://www.iso.org/obp/ui/#iso:std:iso-iec:2382:ed-1:v2:en>

    The latter implies that you can't have octets on a system with,
    say, 16-bit bytes, which doesn't match what I would have expected.

    I suspect that ambiguity is unintentional.

    I would think it would be reasonable to say that a system with
    16-bit bytes has, say, 32k bytes or 64k octets of memory. But C
    doesn't use the word "octet", so this is at best marginally topical.

    I wonder. For word oriented systems, it was common to describe
    memory in terms of words (e.g., "the KL-10B processor with
    extended addressing supports a maximum of 4 MW of memory...").
    Similarly, even for byte-addressed machines, like the PDP-11,
    memory capacities were often described in terms of 16-bit words
    ("this machine has 256 KW of memory", aka, 512 KB). [Of course,
    these machines all predate common use if the "Ki" and "Mi"
    units). Anyway, there is some precedent for using the machine
    specific sizes in discussion, though I agree generally that
    using octets makes sense in this context.

    None of this has much to do with C, though, as you point out.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@Keith.S.Thompson+u@gmail.com to comp.lang.c on Thu May 14 19:04:50 2026
    From Newsgroup: comp.lang.c

    Bart <bc@freeuk.com> writes:
    [...]
    It's not really helped by having having a table that combines
    precedences of different kinds of operator.
    [...]

    C has postfix, unary, binary, and ternary operators. You claim to
    dislike the fact that all those operators are commonly shown in one
    table. I don't know whether you would prefer the postfix and unary
    operators to be left out, or shown in one or two separate tables.
    The only ternary operator is the conditional operator; its precedence
    is *between* the precedence of the "||" and "==" operators, but
    apparently you dislike the inclusion of the conditional operator
    in tables of operator precedences.

    I can think of no reason for your complaint other than that you
    like arguing.

    If you have an actual point, perhaps you could show us a C operator
    precedence table that you like better than Table 2-1 in K&R2,
    and explain to us why you think it's better.

    Or were you being figurative?
    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@Keith.S.Thompson+u@gmail.com to comp.lang.c on Thu May 14 19:12:43 2026
    From Newsgroup: comp.lang.c

    cross@spitfire.i.gajendra.net (Dan Cross) writes:
    In article <10u5m4m$uo0d$3@kst.eternal-september.org>,
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
    cross@spitfire.i.gajendra.net (Dan Cross) writes:
    [...]
    At this point, the term "byte" has been standardized by several
    different bodies (IEC, ISO) to be synonymous with octet. The
    continued use of "octet" by organizations like the IETF is
    mostly a legacy curiosity.

    Has it?

    Yes. IEC 80000-13 declares them to be synonyms.

    Interesting. It's odd that ISO/IEC 2382 and ISO/IEC 80000-13
    disagree with each other.

    <https://www.iso.org/standard/87648.html>
    IEC 80000-13:2025 Quantities and units
    Part 13: Information science and technology

    I'm not going to spend 115 Swiss Francs (currently
    146.39 USD) to get a copy.

    If you have a copy, can you quote the relevant wording?

    [...]
    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@cross@spitfire.i.gajendra.net (Dan Cross) to comp.lang.c on Fri May 15 02:20:46 2026
    From Newsgroup: comp.lang.c

    In article <10u5ver$uo0d$11@kst.eternal-september.org>,
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote: >cross@spitfire.i.gajendra.net (Dan Cross) writes:
    In article <10u5m4m$uo0d$3@kst.eternal-september.org>,
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote: >>>cross@spitfire.i.gajendra.net (Dan Cross) writes:
    [...]
    At this point, the term "byte" has been standardized by several
    different bodies (IEC, ISO) to be synonymous with octet. The
    continued use of "octet" by organizations like the IETF is
    mostly a legacy curiosity.

    Has it?

    Yes. IEC 80000-13 declares them to be synonyms.

    Interesting. It's odd that ISO/IEC 2382 and ISO/IEC 80000-13
    disagree with each other.

    <https://www.iso.org/standard/87648.html>
    IEC 80000-13:2025 Quantities and units
    Part 13: Information science and technology

    I'm not going to spend 115 Swiss Francs (currently
    146.39 USD) to get a copy.

    If you have a copy, can you quote the relevant wording?

    Sure.

    |The specified data elements depend on the organization of the
    |storage device, for example, binary elements (also called
    |"bits"), octets (also called "bytes"), words of a given
    |number of bits, blocks. A subscript referring to a specified
    |data element can be added to the symbol.
    |
    | ...
    |
    |When used to express a storage capacity or an equivalent binary
    |storage capacity, the bit and the octet (or byte) may be
    |combined with SI prefixes or prefixes for binary multiples.
    |
    |In English, the name "byte", symbol B, is used as a synonym
    |for "octet". Here, "byte" means an eight-bit byte. However,
    |"byte" has been used for numbers of bits other than eight. To
    |avoid the risk of confusion, it is strongly recommended that
    |the name "byte" and the symbol B be used only for eight-bit
    |bytes.

    Note that they do acknowledge the historical usage, but it's
    clear they are defining "byte" and "octet" to mean the same
    thing.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@david.brown@hesbynett.no to comp.lang.c on Fri May 15 10:27:19 2026
    From Newsgroup: comp.lang.c

    On 15/05/2026 02:52, Janis Papanagnou wrote:
    On 2026-05-14 20:50, David Brown wrote:
    On 14/05/2026 20:19, Bart wrote:
    [...]

    I certainly agree it would be odd if there were binary arithmetic
    operators with higher precedence than unary operators.  [...]

    I've just posted an example; exponentiation. It depends on the
    language. (Below examples from Algol 68 and Awk...)

    $ genie -p '-2^4'
                     +16
    $ awk 'BEGIN{print -2^4}'
    -16


    Fair enough. Exponentiation is a binary operator (in languages that
    have it) that would - to fit with normal maths usage - have higher
    precedence than things like unary minus.

    Thanks for that example - even though C does not have such an operator,
    it's worth remembering.

    But (I think; unless that has changed) "C" has no exponentiation
    operator, so it doesn't apply here at least.

    But if you start with any new language you have to inspect the
    documentation about its operators and their precedence rules.

    Janis


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@david.brown@hesbynett.no to comp.lang.c on Fri May 15 10:32:00 2026
    From Newsgroup: comp.lang.c

    On 15/05/2026 02:31, Bart wrote:
    On 15/05/2026 00:40, Keith Thompson wrote:
    Bart <bc@freeuk.com> writes:
    [...]
    Unary operators aren't the problem. It's a mystery why they need to be
    in a table at all. Nobody's going to think that '&a + b' means '&(a +
    b)'.
    [...]

    It would be silly for an operator precedence tables to omit the
    operators that "everybody knows".  If I had a table that didn't
    show *all* the operators, I'd look for a better table (like the
    one in K&R2).

    Do you need to know the precedence of a unary operator (say applied to
    any of these terms) in order to correctly parse this:

       a op1 b op2 c

    ?

    'a b c' are terms, and 'op1 op2' are operators. You need to know their relative precedences in order to correctly parse this as either '(a op1
    b) op2 c' or 'a op1 (b op2 c)'. Any unary ops on those terms don't
    affect that.


    That argument makes no sense.

    You don't need to know where binary "-" fits in the precedence ordering
    in order to correctly parse :

    a + b / c

    However, I doubt if you would be happy with a table of operators that
    omitted binary minus.

    Yes, it would be possible to draw tables of C operator precedence where
    you had separate tables for each type of operator, and then a separate description of how they fit together. But it is a lot simpler, clearer
    and easier to use if you have a table that includes them all.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@Keith.S.Thompson+u@gmail.com to comp.lang.c on Fri May 15 02:35:51 2026
    From Newsgroup: comp.lang.c

    David Brown <david.brown@hesbynett.no> writes:
    On 15/05/2026 02:31, Bart wrote:
    [...]
    Do you need to know the precedence of a unary operator (say applied
    to any of these terms) in order to correctly parse this:
       a op1 b op2 c
    ?
    'a b c' are terms, and 'op1 op2' are operators. You need to know
    their relative precedences in order to correctly parse this as
    either '(a op1 b) op2 c' or 'a op1 (b op2 c)'. Any unary ops on
    those terms don't affect that.

    That argument makes no sense.

    I suspect Bart intended that any of the terms a, b, c could include
    a unary operator, so for example "a op1 b op2 c" might actually
    be "-x op1 !y op2 ~z". And because of that, I guess, you don't
    need to worry about the precedence of the unary operators because
    they're obvious?

    I don't agree with his conclusion at all, but I *think* I see
    what he was trying to say.

    This is at least partly speculative, and I'm sure Bart can correct
    me if I'm mistaken.

    [...]
    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From tTh@tth@none.invalid to comp.lang.c on Fri May 15 12:25:52 2026
    From Newsgroup: comp.lang.c

    On 5/15/26 02:52, Janis Papanagnou wrote:

    $ awk 'BEGIN{print -2^4}'
    -16

    tth@linda:~/Desktop$ awk 'BEGIN{print -2^4}'
    -16
    tth@linda:~/Desktop$ awk 'BEGIN{print (-2)^4}'
    16

    Computing is an evil science :)
    --
    ** **
    * tTh des Bourtoulots *
    * http://maison.tth.netlib.re/ *
    ** **
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Bart@bc@freeuk.com to comp.lang.c on Fri May 15 11:38:15 2026
    From Newsgroup: comp.lang.c

    On 15/05/2026 09:32, David Brown wrote:
    On 15/05/2026 02:31, Bart wrote:
    On 15/05/2026 00:40, Keith Thompson wrote:
    Bart <bc@freeuk.com> writes:
    [...]
    Unary operators aren't the problem. It's a mystery why they need to be >>>> in a table at all. Nobody's going to think that '&a + b' means '&(a +
    b)'.
    [...]

    It would be silly for an operator precedence tables to omit the
    operators that "everybody knows".  If I had a table that didn't
    show *all* the operators, I'd look for a better table (like the
    one in K&R2).

    Do you need to know the precedence of a unary operator (say applied to
    any of these terms) in order to correctly parse this:

        a op1 b op2 c

    ?

    'a b c' are terms, and 'op1 op2' are operators. You need to know their
    relative precedences in order to correctly parse this as either '(a
    op1 b) op2 c' or 'a op1 (b op2 c)'. Any unary ops on those terms don't
    affect that.


    That argument makes no sense.

    You don't need to know where binary "-" fits in the precedence ordering
    in order to correctly parse :

        a + b / c

    However, I doubt if you would be happy with a table of operators that omitted binary minus.

    What do you mean by 'binary "-"' and 'binary minus'? Are they both the operator in "x - y" or did one or both mean the unary negation operator
    in "-z"?

    In my example, 'a b c' each represent arbitrary terms. These are
    examples of such terms:

    -x
    &x
    ++x[i]
    x(i, j)
    (x + y)
    x.m--
    -(+(-(sizeof(x))))

    These include some unary operators. But they don't influence how 'a op1
    b op2 c' is parsed.

    At least not in C. Some languages may have special rules so that:

    -a**b is parsed as -(a**b)
    not a or b is parsed as not (a or b)


    Yes, it would be possible to draw tables of C operator precedence where
    you had separate tables for each type of operator, and then a separate description of how they fit together.  But it is a lot simpler, clearer
    and easier to use if you have a table that includes them all.


    Disagree: in C, the only thing I've used the precedence table for is for
    the relative precedence of op1 and op2 in examples like mine.

    It's not even useful inside C compilers; you tend to follow the grammar
    rather than have it table-driven using such a chart.



    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Adam Sampson@ats@offog.org to comp.lang.c on Fri May 15 11:55:18 2026
    From Newsgroup: comp.lang.c

    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

    "switch" was originally implemented in a way that, I suspect, was
    easier for the compiler to implement

    It would also have been familiar from BCPL. When C was designed, switch
    would have been recognised as a direct equivalent of BCPL's SWITCHON
    construct:

    https://archive.org/details/bcpl_20200522/page/19/mode/2up

    There's no equivalent of break in that version of BCPL; if you look at
    example code from that era (e.g. the Xerox Alto BCPL manuals), the
    convention was to use GOTO at the end of each case with a label after
    the block. Later versions of BCPL have ENDCASE which works like break:

    https://archive.org/details/DTIC_ADA003599/page/41/mode/2up

    (and I wonder whether this was influenced by C).
    --
    Adam Sampson <ats@offog.org> <http://offog.org/>
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@cross@spitfire.i.gajendra.net (Dan Cross) to comp.lang.c on Fri May 15 11:27:53 2026
    From Newsgroup: comp.lang.c

    In article <y2av7cpq6w9.fsf@offog.org>, Adam Sampson <ats@offog.org> wrote: >Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

    "switch" was originally implemented in a way that, I suspect, was
    easier for the compiler to implement

    It would also have been familiar from BCPL. When C was designed, switch
    would have been recognised as a direct equivalent of BCPL's SWITCHON >construct:

    https://archive.org/details/bcpl_20200522/page/19/mode/2up

    There's no equivalent of break in that version of BCPL; if you look at >example code from that era (e.g. the Xerox Alto BCPL manuals), the
    convention was to use GOTO at the end of each case with a label after
    the block. Later versions of BCPL have ENDCASE which works like break:

    https://archive.org/details/DTIC_ADA003599/page/41/mode/2up

    (and I wonder whether this was influenced by C).

    It almost certainly was, as C did exert some influence on its
    ancestor throughout the 1980s. For instance, when C was written
    the only comment indicator in BCPL was `//` (which some
    erroneously assume originated in C++). The `/* ... */` syntax
    was absent, but _was_ later incorporated, due to its prevalence
    brought forth by the popularity C. C inherited that syntax from
    PL/1.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@cross@spitfire.i.gajendra.net (Dan Cross) to comp.lang.c on Fri May 15 11:35:51 2026
    From Newsgroup: comp.lang.c

    In article <10u6t2n$4mai$1@dont-email.me>, Bart <bc@freeuk.com> wrote:
    On 15/05/2026 09:32, David Brown wrote:
    On 15/05/2026 02:31, Bart wrote:
    On 15/05/2026 00:40, Keith Thompson wrote:
    Bart <bc@freeuk.com> writes:
    [...]
    Unary operators aren't the problem. It's a mystery why they need to be >>>>> in a table at all. Nobody's going to think that '&a + b' means '&(a + >>>>> b)'.
    [...]

    It would be silly for an operator precedence tables to omit the
    operators that "everybody knows".  If I had a table that didn't
    show *all* the operators, I'd look for a better table (like the
    one in K&R2).

    Do you need to know the precedence of a unary operator (say applied to
    any of these terms) in order to correctly parse this:

        a op1 b op2 c

    ?

    'a b c' are terms, and 'op1 op2' are operators. You need to know their
    relative precedences in order to correctly parse this as either '(a
    op1 b) op2 c' or 'a op1 (b op2 c)'. Any unary ops on those terms don't
    affect that.


    That argument makes no sense.

    You don't need to know where binary "-" fits in the precedence ordering
    in order to correctly parse :

        a + b / c

    However, I doubt if you would be happy with a table of operators that
    omitted binary minus.

    What do you mean by 'binary "-"' and 'binary minus'?

    As a binary operator, `-` refers to subtraction. Note that the
    expression quoted above does not contain subtraction. Therefore
    one does to need to know the precedence of the subtraction
    operator to parse that expression.

    'binary "-"' and 'binary minus' mean the same thing; in the
    former he used a literal `-` character, and in the latter he
    substituted the name of the symbol.

    Are they both the
    operator in "x - y" or did one or both mean the unary negation operator
    in "-z"?

    It says it right there on the tin, dude. It ain't that hard.

    Yes, it would be possible to draw tables of C operator precedence where
    you had separate tables for each type of operator, and then a separate
    description of how they fit together.  But it is a lot simpler, clearer
    and easier to use if you have a table that includes them all.

    Disagree: in C, the only thing I've used the precedence table for is for
    the relative precedence of op1 and op2 in examples like mine.

    Not the flex you think it is....

    It's not even useful inside C compilers; you tend to follow the grammar >rather than have it table-driven using such a chart.

    Well, it is a good thing that there is no table like that in the
    C standard, then, but instead a grammar that shows precedence.

    Tables like that are meant for quick reference by working
    programmers, not as normative sources for compiler implementers.

    - Dan C

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Bart@bc@freeuk.com to comp.lang.c on Fri May 15 12:43:47 2026
    From Newsgroup: comp.lang.c

    On 15/05/2026 11:55, Adam Sampson wrote:
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

    "switch" was originally implemented in a way that, I suspect, was
    easier for the compiler to implement

    It would also have been familiar from BCPL. When C was designed, switch
    would have been recognised as a direct equivalent of BCPL's SWITCHON construct:

    https://archive.org/details/bcpl_20200522/page/19/mode/2up


    That mentions labels existing within a block. It doesn't say if labels
    can also exist within nested blocks, as happens in C, which allows
    switch to be more chaotic.

    Actually, in C, you don't even need any block after 'switch'.


    There's no equivalent of break in that version of BCPL; if you look at example code from that era (e.g. the Xerox Alto BCPL manuals), the
    convention was to use GOTO at the end of each case with a label after
    the block. Later versions of BCPL have ENDCASE which works like break:

    https://archive.org/details/DTIC_ADA003599/page/41/mode/2up

    It's not clear what the rules are: if the syntax requires CASE ...
    ENDCASE without nesting or overlapping, then this is better formed than C.

    But this would make it harder to do CASE 1: CASE 2:... ENDCASE, unless consective CASEs are considered one label that is terminated by one ENDCASE.


    (and I wonder whether this was influenced by C).

    The previous page shows this form of FOR loop:

    for N = El to E2 do C

    where N is a name.

    It seems C didn't copy this, neither did it influence BCPL.




    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@david.brown@hesbynett.no to comp.lang.c on Fri May 15 13:44:20 2026
    From Newsgroup: comp.lang.c

    On 15/05/2026 03:56, Dan Cross wrote:
    In article <10u5m4m$uo0d$3@kst.eternal-september.org>,
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
    cross@spitfire.i.gajendra.net (Dan Cross) writes:
    In article <86pl2yi0n3.fsf@linuxsc.com>,
    Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:
    [...]

    Also, the "k" suffix formally means 1000, but is often used to mean
    1024, which is why we have "Ki", "kibi" to denote a power of two
    explicitly.

    Yes. K, M, G, etc, have always been the SI indicators for
    powers of 10, not powers of 2. The "Ki", "Mi", "Gi", etc, forms
    are (as I understand it) relatively new.


    They are also very rarely used, IME. People who care about these things already know that 1 KB is 1024 bytes, not 1000 bytes. (There was a big
    to-do about disk sizes a number of years ago, where disks were marketed
    using 1000-based units but users expected 1024-based units.)

    [...]]

    At this point, the term "byte" has been standardized by several
    different bodies (IEC, ISO) to be synonymous with octet. The
    continued use of "octet" by organizations like the IETF is
    mostly a legacy curiosity.

    Has it?

    Yes. IEC 80000-13 declares them to be synonyms.

    The ISO C and C++ standards certainly do not use "byte"
    to mean exactly 8 bits.

    Indeed. I don't blame them. I suspect there are some DSP chips
    or weird one-off processors with oddball byte sizes, even now.


    There certainly are. But on these systems, IME no one ever uses the
    word "byte" to refer to anything other than 8 bits. Sizes are generally
    given explicitly, or refer to "unsigned char" (which will be perhaps
    12-bit or 16-bit), or sometimes a more generic term like "word" will be
    used. When you read the manual for a CHAR_BIT 16 compiler for a DSP (at
    least for the two that I have read), you won't see the term "byte"
    referring to anything other than 8 bits.


    I would think it would be reasonable to say that a system with
    16-bit bytes has, say, 32k bytes or 64k octets of memory. But C
    doesn't use the word "octet", so this is at best marginally topical.

    I wonder. For word oriented systems, it was common to describe
    memory in terms of words (e.g., "the KL-10B processor with
    extended addressing supports a maximum of 4 MW of memory...").

    That is the norm in the embedded world. While it is mostly just DSP's
    that have char greater than 8 bits, it is not uncommon to have flash or
    other program memory that is wider than 8 bits. An AVR microcontroller
    might be said to have 16 kW or 32 kB of memory, where each word of flash
    is 16 bits. For PIC microcontrollers, kW is common since each word of
    program memory might be 12, 14 or 16 bits according to the family.
    (These are Harvard architecture devices - data memory is entirely
    separate from code memory.)

    Similarly, even for byte-addressed machines, like the PDP-11,
    memory capacities were often described in terms of 16-bit words
    ("this machine has 256 KW of memory", aka, 512 KB). [Of course,
    these machines all predate common use if the "Ki" and "Mi"
    units). Anyway, there is some precedent for using the machine
    specific sizes in discussion, though I agree generally that
    using octets makes sense in this context.

    None of this has much to do with C, though, as you point out.

    - Dan C.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@david.brown@hesbynett.no to comp.lang.c on Fri May 15 13:58:37 2026
    From Newsgroup: comp.lang.c

    On 15/05/2026 12:38, Bart wrote:
    On 15/05/2026 09:32, David Brown wrote:
    On 15/05/2026 02:31, Bart wrote:
    On 15/05/2026 00:40, Keith Thompson wrote:
    Bart <bc@freeuk.com> writes:
    [...]
    Unary operators aren't the problem. It's a mystery why they need to be >>>>> in a table at all. Nobody's going to think that '&a + b' means '&(a + >>>>> b)'.
    [...]

    It would be silly for an operator precedence tables to omit the
    operators that "everybody knows".  If I had a table that didn't
    show *all* the operators, I'd look for a better table (like the
    one in K&R2).

    Do you need to know the precedence of a unary operator (say applied
    to any of these terms) in order to correctly parse this:

        a op1 b op2 c

    ?

    'a b c' are terms, and 'op1 op2' are operators. You need to know
    their relative precedences in order to correctly parse this as either
    '(a op1 b) op2 c' or 'a op1 (b op2 c)'. Any unary ops on those terms
    don't affect that.


    That argument makes no sense.

    You don't need to know where binary "-" fits in the precedence
    ordering in order to correctly parse :

         a + b / c

    However, I doubt if you would be happy with a table of operators that
    omitted binary minus.

    What do you mean by 'binary "-"' and 'binary minus'? Are they both the operator in "x - y" or did one or both mean the unary negation operator
    in "-z"?


    I meant "binary minus", written either "minus" or "-". If I had meant
    unary minus or negation, I would not have written "binary".

    In my example, 'a b c' each represent arbitrary terms. These are
    examples of such terms:

       -x
       &x
       ++x[i]
       x(i, j)
       (x + y)
       x.m--
       -(+(-(sizeof(x))))


    Yes. So?

    What you wrote is that if you have an expression where only the binary operators are of relevance or interest, you only need a table of the
    binary operators in order to understand the interaction between them.

    I pointed out that the same logic applies if you have an expression
    where only some binary operators are used - you only need a table with
    those binary operators in order to understand the interactions.

    There is no benefit in having multiple tables for the normal operators
    in a language - it is simpler and clearer to put them all in one table. Isolating the unary operators is no more logical or useful than
    isolating the binary minus operator.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Bart@bc@freeuk.com to comp.lang.c on Fri May 15 13:05:45 2026
    From Newsgroup: comp.lang.c

    On 15/05/2026 12:35, Dan Cross wrote:
    In article <10u6t2n$4mai$1@dont-email.me>, Bart <bc@freeuk.com> wrote:
    On 15/05/2026 09:32, David Brown wrote:
    On 15/05/2026 02:31, Bart wrote:
    On 15/05/2026 00:40, Keith Thompson wrote:
    Bart <bc@freeuk.com> writes:
    [...]
    Unary operators aren't the problem. It's a mystery why they need to be >>>>>> in a table at all. Nobody's going to think that '&a + b' means '&(a + >>>>>> b)'.
    [...]

    It would be silly for an operator precedence tables to omit the
    operators that "everybody knows".  If I had a table that didn't
    show *all* the operators, I'd look for a better table (like the
    one in K&R2).

    Do you need to know the precedence of a unary operator (say applied to >>>> any of these terms) in order to correctly parse this:

        a op1 b op2 c

    ?

    'a b c' are terms, and 'op1 op2' are operators. You need to know their >>>> relative precedences in order to correctly parse this as either '(a
    op1 b) op2 c' or 'a op1 (b op2 c)'. Any unary ops on those terms don't >>>> affect that.


    That argument makes no sense.

    You don't need to know where binary "-" fits in the precedence ordering
    in order to correctly parse :

        a + b / c

    However, I doubt if you would be happy with a table of operators that
    omitted binary minus.

    What do you mean by 'binary "-"' and 'binary minus'?

    As a binary operator, `-` refers to subtraction. Note that the
    expression quoted above does not contain subtraction. Therefore
    one does to need to know the precedence of the subtraction
    operator to parse that expression.

    'binary "-"' and 'binary minus' mean the same thing; in the
    former he used a literal `-` character, and in the latter he
    substituted the name of the symbol.

    Are they both the
    operator in "x - y" or did one or both mean the unary negation operator
    in "-z"?

    It says it right there on the tin, dude. It ain't that hard.

    No need to be impertinent. There was ambiguity in DB's comment:

    * I suggested that unary operators (including unary minus) doesn't
    belong in a chart of precedences which is mostly about binary ops

    * He says: "I doubt if you would be happy with a table of operators that
    omitted binary minus"

    I hadn't suggested that the binary or dyadic "-" operator should be
    omitted. So I tried to clear things up.

    Disagree: in C, the only thing I've used the precedence table for is for
    the relative precedence of op1 and op2 in examples like mine.

    Not the flex you think it is....

    Jesus. Just stop with the putdowns.

    I'm pretty sure very, very many people have the same experience: does
    "^" come before or after "|"? They look at the table.

    How many need to look up whether unary "!" comes before or after "^"? It
    just doesn't happen. You can't change the fixed meaning of 'a | !b'
    using parentheses.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Bart@bc@freeuk.com to comp.lang.c on Fri May 15 14:54:01 2026
    From Newsgroup: comp.lang.c

    On 15/05/2026 12:58, David Brown wrote:
    On 15/05/2026 12:38, Bart wrote:
    On 15/05/2026 09:32, David Brown wrote:

    However, I doubt if you would be happy with a table of operators that
    omitted binary minus.

    What do you mean by 'binary "-"' and 'binary minus'? Are they both the
    operator in "x - y" or did one or both mean the unary negation
    operator in "-z"?


    I meant "binary minus", written either "minus" or "-".  If I had meant unary minus or negation, I would not have written "binary".

    In my example, 'a b c' each represent arbitrary terms. These are
    examples of such terms:

        -x
        &x
        ++x[i]
        x(i, j)
        (x + y)
        x.m--
        -(+(-(sizeof(x))))


    Yes.  So?

    See below.


    What you wrote is that if you have an expression where only the binary operators are of relevance or interest, you only need a table of the
    binary operators in order to understand the interaction between them.

    Yes.

    I pointed out that the same logic applies if you have an expression
    where only some binary operators are used - you only need a table with
    those binary operators in order to understand the interactions.

    I didn't imply a dedicated table for each possible expression that can
    be written in C.

    There is one such table for all programs.

    Possibly you misunderstood my example. Let me rewrite it as:

    Term binop1 Term binop2 Term

    Examples of a Term are given above.

    Parsing this involves knowing /only/ about binop precedences. Any unary
    ops are contained within any of those Terms and don't affect this at all.

    There is no benefit in having multiple tables for the normal operators
    in a language - it is simpler and clearer to put them all in one table. Isolating the unary operators is no more logical or useful than
    isolating the binary minus operator.

    I'm saying that unary operators don't need to be in ANY table!

    In fact, the C standard doesn't seem to have any such table; precedence
    is implied by the grammar, but in the same way as the rest of the syntax.

    Precedence tables come up elsewhere, and they invariably mix up binary
    ops with unary ops and postfix ops.

    The latter include (), [] and ".".

    Prefix and Postfix ops together, when clustered around a specific term,
    have their own set of rules. They are quite different from binary ops.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Bart@bc@freeuk.com to comp.lang.c on Fri May 15 15:00:39 2026
    From Newsgroup: comp.lang.c

    On 15/05/2026 14:54, Bart wrote:


    Prefix and Postfix ops together, when clustered around a specific term,
    have their own set of rules. They are quite different from binary ops.

    I'm going to bail out here. This is not going anywhere.

    Either people don't understand the subject, or are pretending not to, or
    just want to have a go.

    I have quite a bit of knowledge and practical experience of the subject,
    even if people here don't like to admit that, but I'm poor at getting
    the point across.

    I will reconsider my claim that precedence tables don't need to include anything beyond binary ops, if somebody can give a reference to such a
    table in the C standard.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From scott@scott@slp53.sl.home (Scott Lurndal) to comp.lang.c on Fri May 15 15:45:26 2026
    From Newsgroup: comp.lang.c

    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    scott@slp53.sl.home (Scott Lurndal) writes:
    cross@spitfire.i.gajendra.net (Dan Cross) writes:
    In article <10u2jpk$2t96p$6@kst.eternal-september.org>,
    [...]
    If C's switch statement were to be
    changed, it would have to use something that's currently a syntax >>>>error. Perhaps something like

    case 1, case 2, case 3, case 4: whatever();

    Sure, that's better.

    case 1...4: whatever();

    is a typical GCC extension (that we use heavily).

    Yes, and the C2y draft adopts that syntax.

    (One possible reason it wasn't adopted sooner is that `case 'a'...'z'` >doesn't necessarily work if the letters are not contiguous, for
    example in EBCDIC.)

    I think that's a bit far-fetched. Regular expressions
    have the same EBCDIC related issues (i.e. the discontinuous
    nature of the EBCDIC alpha translations); yet, there are
    no other defined characters in the gaps between the
    alpha groups in EBCDIC, so [a-z] or "case 'a'...'z':" would
    probably work just fine in most cases to match lowercase EBCDIC
    alpha text.

    Worse case, it could be coded as

    case 'a'...'i': /* FALLTHROUGH */
    case 'j'...'r': /* FALLTHROUGH */
    case 's'...'z':
    do something;
    break;

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From scott@scott@slp53.sl.home (Scott Lurndal) to comp.lang.c on Fri May 15 16:01:28 2026
    From Newsgroup: comp.lang.c

    Bart <bc@freeuk.com> writes:
    On 15/05/2026 14:54, Bart wrote:


    Prefix and Postfix ops together, when clustered around a specific term,
    have their own set of rules. They are quite different from binary ops.

    I'm going to bail out here. This is not going anywhere.

    Either people don't understand the subject, or are pretending not to, or >just want to have a go.

    I have quite a bit of knowledge and practical experience of the subject, >even if people here don't like to admit that, but I'm poor at getting
    the point across.

    I will reconsider my claim that precedence tables don't need to include >anything beyond binary ops, if somebody can give a reference to such a
    table in the C standard.

    Given that 99.9% of all programmers learn C without ever referring to
    the C standard, you're being disingenous by requiring a reference to
    a table in the standard.

    I'll point you to page 53 in the K&R Second Edition for a precedence table (2-1)
    that includes the unary ops (albeit in a footnote) that notes"

    "unary +, - and * have higher precedence than the binary forms"

    The text that accompanies the table details, with examples, the
    precedence and order of evaluation.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.c on Fri May 15 20:17:30 2026
    From Newsgroup: comp.lang.c

    On 2026-05-15 17:45, Scott Lurndal wrote:
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    [...]

    (One possible reason it wasn't adopted sooner is that `case 'a'...'z'`
    doesn't necessarily work if the letters are not contiguous, for
    example in EBCDIC.)

    In case of programming languages they at least *could* define
    an _appropriate semantics_ for such ranges, independent of the
    numeric code point in the character table. (Hardly for "C", I
    suppose, when something like 'a' is just an integer.)


    I think that's a bit far-fetched. Regular expressions
    have the same EBCDIC related issues (i.e. the discontinuous
    nature of the EBCDIC alpha translations); yet, there are
    no other defined characters in the gaps between the
    alpha groups in EBCDIC, so [a-z] or "case 'a'...'z':" would
    probably work just fine in most cases to match lowercase EBCDIC
    alpha text.

    I wouldn't count on that and use, in case of Regular Expressions,
    the character classes; [[:alpha:]], [[:upper:]], and [[:lower:]],
    respectively.


    Worse case, it could be coded as

    case 'a'...'i': /* FALLTHROUGH */
    case 'j'...'r': /* FALLTHROUGH */
    case 's'...'z':
    do something;
    break;

    Which I'd consider to be very ugly, especially given that here you
    hard-code your logic for a specific character code table. - Quite anachronistic, I'd say, if not non-sophisticated.

    Curious; is anyone still programming on EBCDIC systems?

    Janis

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@Keith.S.Thompson+u@gmail.com to comp.lang.c on Fri May 15 12:23:52 2026
    From Newsgroup: comp.lang.c

    Bart <bc@freeuk.com> writes:
    On 15/05/2026 14:54, Bart wrote:
    Prefix and Postfix ops together, when clustered around a specific
    term, have their own set of rules. They are quite different from
    binary ops.

    I'm going to bail out here. This is not going anywhere.

    Either people don't understand the subject, or are pretending not to,
    or just want to have a go.

    I have quite a bit of knowledge and practical experience of the
    subject, even if people here don't like to admit that, but I'm poor at getting the point across.

    I think that most of us found your idea that precedence tables
    should exclude unary ops to be so bizarre that we weren't sure you
    actually meant it.

    If you prefer such tables, that's fine. It apparently works for
    you, and it doesn't affect anyone else. If you insist that your
    preference is the one and only right way to construct a precedence
    table, you're going to get some pushback.

    I will reconsider my claim that precedence tables don't need to
    include anything beyond binary ops, if somebody can give a reference
    to such a table in the C standard.

    That's disingenuous. You know, because you've been told several
    times in this thread, that there is precedence table in the C
    standard. You also know that there is a precedence table, that
    includes unary, postfix, binary, and ternary operators, in K&R2.

    Your personal preference for a precedence table that excludes unary
    and postfix operators is perfectly valid for you. Other people's
    preference for a table that includes all the operators is perfectly
    valid for them. (The evidence so far suggests that the latter
    includes everyone but you.)

    You need to understand that your personal preferences, while they may
    be perfectly valid, are unusual, and I advise you to stop trying to
    pretend that they're some kind of universal truth. You've wasted
    a lot of time here arguing that precedence tables *should* omit
    unary and postfix operators, when in fact it's nothing more than
    your personal preference, one not shared by others.
    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@Keith.S.Thompson+u@gmail.com to comp.lang.c on Fri May 15 12:47:04 2026
    From Newsgroup: comp.lang.c

    scott@slp53.sl.home (Scott Lurndal) writes:
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    scott@slp53.sl.home (Scott Lurndal) writes:
    cross@spitfire.i.gajendra.net (Dan Cross) writes:
    In article <10u2jpk$2t96p$6@kst.eternal-september.org>,
    [...]
    If C's switch statement were to be
    changed, it would have to use something that's currently a syntax >>>>>error. Perhaps something like

    case 1, case 2, case 3, case 4: whatever();

    Sure, that's better.

    case 1...4: whatever();

    is a typical GCC extension (that we use heavily).

    Yes, and the C2y draft adopts that syntax.

    (One possible reason it wasn't adopted sooner is that `case 'a'...'z'` >>doesn't necessarily work if the letters are not contiguous, for
    example in EBCDIC.)

    I think that's a bit far-fetched. Regular expressions
    have the same EBCDIC related issues (i.e. the discontinuous
    nature of the EBCDIC alpha translations); yet, there are
    no other defined characters in the gaps between the
    alpha groups in EBCDIC, so [a-z] or "case 'a'...'z':" would
    probably work just fine in most cases to match lowercase EBCDIC
    alpha text.

    I understand there are different versions of EBCDIC. According to
    the table in the Wikipedia article, '~' is between 'r' and 's',
    '}' is between 'I' and 'J', and '\\' is between 'R' and 'S'.

    ISO C has no support for regular expressions.

    Worse case, it could be coded as

    case 'a'...'i': /* FALLTHROUGH */
    case 'j'...'r': /* FALLTHROUGH */
    case 's'...'z':
    do something;
    break;

    In fact EBCDIC, though not mentioned by name, was part of the reason for
    not supporting case ranges. Quoting the ANSI C Rationale:

    Case ranges (of the form lo .. hi) were seriously considered,
    but ultimately not adopted in the Standard on the grounds
    that it added no new capability, just a problematic coding
    convenience. The construct seems to promise more than it could
    be mandated to deliver:

    - A great deal of code (or jump table space) might be generated
    for an innocent-looking case range such as 0 .. 65535.

    - The range 'A'..'Z' would specify all the integers between
    the character code for A and that for Z. In some common
    character sets this range would include non-alphabetic
    characters, and in others it might not include all the
    alphabetic characters (especially in non-English character
    sets).

    No serious consideration was given to making the switch more
    structured, as in Pascal, out of fear of invalidating working
    code.

    gcc and C2Y use "..." rather than ".." because it's an existing token,
    used in variadic function declarations. `1..4` is actually a
    preprocessing number, resulting in a syntax error when it's
    converted to an integer constant.
    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@Keith.S.Thompson+u@gmail.com to comp.lang.c on Fri May 15 12:54:09 2026
    From Newsgroup: comp.lang.c

    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    Bart <bc@freeuk.com> writes:
    [...]
    I will reconsider my claim that precedence tables don't need to
    include anything beyond binary ops, if somebody can give a reference
    to such a table in the C standard.

    That's disingenuous. You know, because you've been told several
    times in this thread, that there is precedence table in the C
    standard. You also know that there is a precedence table, that
    includes unary, postfix, binary, and ternary operators, in K&R2.

    Sorry, editing error. I meant that there is *no* precedence table
    in the C standard.
    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@Keith.S.Thompson+u@gmail.com to comp.lang.c on Fri May 15 13:15:44 2026
    From Newsgroup: comp.lang.c

    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    [...]
    gcc and C2Y use "..." rather than ".." because it's an existing token,
    used in variadic function declarations. `1..4` is actually a
    preprocessing number, resulting in a syntax error when it's
    converted to an integer constant.

    That actually raises a couple of interesting issues.

    C2y (N3783) defines:

    constant-range-expression:
    constant-expression ... constant-expression

    with this description:

    A *constant range expression* is a special syntactic form that
    describes a sequence of contiguously incrementing integer
    values ranging from the arithmetic value of the first constant
    expression to the second, without listing intermediate values
    explicitly. The operator is not a value expression and is only
    permitted in specific contexts, such as the operand to a case
    label to indicate that a single label matches multiple values.

    In fact I'm fairly sure that's the only context in which it can
    appear, but I suppose it doesn't hurt to allow for other uses in
    the future.

    It says the *operator* is not a "value expression", a phrase not used
    anywhere else. (Is `...` an operator?) It would be more accurate
    to say that a constant-range-expression is not an expression,
    and IMHO better to use a different name, such as constant-range.

    I had assumed that `case 1...2:` was intended to be valid, but
    due to the maximal munch rule `1...2` is a preprocessing number.
    Both gcc and clang flag it as a syntax error, whether with "-std=c2y"
    (treating it as a standard feature) or without it (treating it as
    an extension).

    So `case '0'...'1' is valid, and so is `case foo...bar:` if
    foo and bar are constant expressions, but `case 1...2:` is not.
    The whitespace is a good idea anyway, but a footnote would be helpful
    -- or perhaps a change in the syntax of preprocessing numbers so
    they can't contain "...".
    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Bart@bc@freeuk.com to comp.lang.c on Fri May 15 21:39:52 2026
    From Newsgroup: comp.lang.c

    On 15/05/2026 20:23, Keith Thompson wrote:
    Bart <bc@freeuk.com> writes:
    On 15/05/2026 14:54, Bart wrote:
    Prefix and Postfix ops together, when clustered around a specific
    term, have their own set of rules. They are quite different from
    binary ops.

    I'm going to bail out here. This is not going anywhere.

    Either people don't understand the subject, or are pretending not to,
    or just want to have a go.

    I have quite a bit of knowledge and practical experience of the
    subject, even if people here don't like to admit that, but I'm poor at
    getting the point across.

    I think that most of us found your idea that precedence tables
    should exclude unary ops to be so bizarre that we weren't sure you
    actually meant it.

    Well, I find it bizarre that they should! Let's see:

    * Infix operators have 13 different precedence levels. Prefix and
    Postfix have one each

    * You can vary evaluation order of infix expressions with parentheses.
    Prefix/Postfix are much more limited (you might force a prefix op to
    be done before a postfix op on the same term, but cannot change the
    order of each set)

    * Half the prefix/postfix aren't even proper operators IMO (see below)

    I mean, have you ever needed to look up a precedence level for anything
    other than an infix operator?


    I will reconsider my claim that precedence tables don't need to
    include anything beyond binary ops, if somebody can give a reference
    to such a table in the C standard.

    That's disingenuous. You know, because you've been told several
    times in this thread, that there is precedence table in the C
    standard.

    Whereabouts?

    You also know that there is a precedence table, that
    includes unary, postfix, binary, and ternary operators, in K&R2.

    Usually you're reluctant refuse to discuss anything that isn't mentioned
    in the standard.

    Your personal preference for a precedence table that excludes unary
    and postfix operators is perfectly valid for you. Other people's
    preference for a table that includes all the operators is perfectly
    valid for them. (The evidence so far suggests that the latter
    includes everyone but you.)


    This is information about Go (from https://rosettacode.org/wiki/Operator_precedence#Go):

    ---------------------------------
    Precedence Operators

    Highest Unary operators: +, -, !, ^, *, &, <-
    5 *, /, %, <<, >>, &, &^
    4 +, -, |, ^
    3 ==, !=, <, <=, >, >=
    2 &&
    1 ||

    Syntactic elements not in the list are not considered operators in Go;
    if they present ambiguity in order of evaluation, the ambiguity is
    resolved by other rules specific to those elements. ---------------------------------

    Notice how much tider it is than C's dozen or so levels AND EASIER TO
    REMEMBER because the choices make sense.

    Although this still includes a section on unary, it is one level only,
    and is again not relevant for someone seeking clarification on an infix op.

    It is sufficient to know that a unary op automatically binds more
    tightly. It's not even given a level number.

    (My own views are also that '() [] .' etc are syntactic elements, not operators. I also have 5 precedence levels for those sets of binary ops
    (but have one more for '**').

    My choices are almost exactly like Go's, except that & is lumped with |
    and ^, since I consider level 5 ops to scale values, but level 4 ops do
    not scale.

    So, the way I think is not as far-out as you suggest. I never looked at
    Go's operators until today; it is telling that my ideas and Google's
    have more or less converged.)

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Bart@bc@freeuk.com to comp.lang.c on Fri May 15 21:52:08 2026
    From Newsgroup: comp.lang.c

    On 13/05/2026 22:46, Scott Lurndal wrote:
    cross@spitfire.i.gajendra.net (Dan Cross) writes:
    In article <10u2jpk$2t96p$6@kst.eternal-september.org>,
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
    cross@spitfire.i.gajendra.net (Dan Cross) writes:
    In article <10u0k0k$1l93l$30@dont-email.me>,
    [...]
    It's easy to get wrong. Other languages accommodate both
    semantics using alternation in the selector arm. For example,
    one might imagine an hypothetical syntax, something like:

    switch (a) {
    case 1 || 2 || 3 || 4: whatever();
    default: other();
    }

    ...with no `break` to end each `case`.

    That's already valid syntax.

    It wasn't meant to be taken as a serious suggestion!

    If C's switch statement were to be
    changed, it would have to use something that's currently a syntax
    error. Perhaps something like

    case 1, case 2, case 3, case 4: whatever();

    Sure, that's better.

    case 1...4: whatever();

    is a typical GCC extension (that we use heavily).

    This is bit of a quandry in C.

    C is zero-based; other zero-based languages tend to have open ranges,
    with an exclusive upper bound. That means that A..B means A to B-1
    inclusive, and 0..N means 0 to N-1.

    Some might use a special syntax to make it clearer, such as 0..<N.

    Other the other hand, an inclusive range is far more intuitive in
    general, such as in 'A'...'Z' and Mon...Fri.

    I guess one more quirk at this point makes little difference.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@Keith.S.Thompson+u@gmail.com to comp.lang.c on Fri May 15 14:14:52 2026
    From Newsgroup: comp.lang.c

    Bart <bc@freeuk.com> writes:
    On 15/05/2026 20:23, Keith Thompson wrote:
    [...]
    I think that most of us found your idea that precedence tables
    should exclude unary ops to be so bizarre that we weren't sure you
    actually meant it.

    Well, I find it bizarre that they should!

    Already acknowledged.

    [...]

    That's disingenuous. You know, because you've been told several
    times in this thread, that there is precedence table in the C
    standard.

    Whereabouts?

    I accidentally omitted a word there. There is *no* precedence
    table in the C standard.

    [...]
    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From scott@scott@slp53.sl.home (Scott Lurndal) to comp.lang.c on Fri May 15 22:16:03 2026
    From Newsgroup: comp.lang.c

    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    scott@slp53.sl.home (Scott Lurndal) writes:
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    scott@slp53.sl.home (Scott Lurndal) writes:
    cross@spitfire.i.gajendra.net (Dan Cross) writes:
    In article <10u2jpk$2t96p$6@kst.eternal-september.org>,
    [...]
    If C's switch statement were to be
    changed, it would have to use something that's currently a syntax >>>>>>error. Perhaps something like

    case 1, case 2, case 3, case 4: whatever();

    Sure, that's better.

    case 1...4: whatever();

    is a typical GCC extension (that we use heavily).

    Yes, and the C2y draft adopts that syntax.

    (One possible reason it wasn't adopted sooner is that `case 'a'...'z'` >>>doesn't necessarily work if the letters are not contiguous, for
    example in EBCDIC.)

    I think that's a bit far-fetched. Regular expressions
    have the same EBCDIC related issues (i.e. the discontinuous
    nature of the EBCDIC alpha translations); yet, there are
    no other defined characters in the gaps between the
    alpha groups in EBCDIC, so [a-z] or "case 'a'...'z':" would
    probably work just fine in most cases to match lowercase EBCDIC
    alpha text.

    I understand there are different versions of EBCDIC. According to
    the table in the Wikipedia article, '~' is between 'r' and 's',
    '}' is between 'I' and 'J', and '\\' is between 'R' and 'S'.

    Ah yes. I had the Burroughs EBCDIC card handy when I wrote that.

    IBM was always fond of doing things their way.

    <snip>


    In fact EBCDIC, though not mentioned by name, was part of the reason for
    not supporting case ranges. Quoting the ANSI C Rationale:

    Ah, hadn't seen that. Makes sense.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.c on Sat May 16 00:44:39 2026
    From Newsgroup: comp.lang.c

    On 2026-05-15 22:39, Bart wrote:
    [...]
    The fewer precedence groups you have the more parentheses you will
    have to use in expressions. And vice versa. - The actual choice is
    a decision of the respective language designers.

    Actually, ranges of about ten levels seem to be not uncommon amongst programming languages to provide a sensible, widely accepted grouping.
    Language designers seem to be trying to avoid a flood of unnecessary parentheses in programs. (Note: that may not apply to Lisp people. :-)

    Janis


    <OT-begin>

    This is information about Go [...]

    [snip table]

    [...]

    And here's a precedence table for another language that facilitates
    that there's no parenthesis at all necessary to obtain unambiguous
    expressions:

    lvl op
    ---------
    1 !!
    2 !§
    3 !$
    4 !%
    5 !/
    6 !+
    7 !~
    8 !=
    9 §!
    10 §§
    11 §$
    12 §%
    13 §/
    14 §+
    15 §~
    16 §=
    17 $!
    18 $§
    19 $$
    20 $%
    21 $/
    22 $+
    23 $~
    24 $=
    25 %!
    26 %§
    27 %$
    28 %%
    29 %/
    30 %+
    31 %~
    32 %=
    33 /!
    34 /§
    35 /$
    36 /%
    37 //
    38 /+
    39 /~
    40 /=
    41 +!
    42 +§
    43 +$
    44 +%
    45 +/
    46 ++
    47 +~
    48 +=
    49 ~!
    50 ~§
    51 ~$
    52 ~%
    53 ~/
    54 ~+
    55 ~~
    56 ~=
    57 =!
    58 =§
    59 =$
    60 =%
    61 =/
    62 =+
    63 =~
    64 ==


    And here a variant with only one level of operator precedence,
    all listed in a single group[*]

    !! !§ !$ !% !/ !+ !~ != §! §§ §$ §% §/ §+ §~ §=
    $! $§ $$ $% $/ $+ $~ $= %! %§ %$ %% %/ %+ %~ %=
    /! /§ /$ /% // /+ /~ /= +! +§ +$ +% +/ ++ +~ +=
    ~! ~§ ~$ ~% ~/ ~+ ~~ ~= =! =§ =$ =% =/ =+ =~ ==

    where sub-expressions will have to be enclosed in parentheses,
    generally.

    [*] "All men, all animals, and all operators are equal!"[**]

    [**] "But some men, animals, and operators are more equal than others!"


    <OT-end>

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Bart@bc@freeuk.com to comp.lang.c on Sat May 16 00:36:35 2026
    From Newsgroup: comp.lang.c

    On 15/05/2026 23:44, Janis Papanagnou wrote:
    On 2026-05-15 22:39, Bart wrote:
    [...]
    The fewer precedence groups you have the more parentheses you will
    have to use in expressions.

    Says whom?

    The more precedence levels there are, the more parentheses need to be
    used because you or your readers can't remember what they are.

    With about the right number, small enough that most people will be able
    to parse intuitvely, parentheses are used to override the default
    priorities.



    And vice versa. - The actual choice is
    a decision of the respective language designers.

    Some language designers, especially in the past (and including me)
    thought that lots of precedence levels was a Feature. It fact it was a worthless one.

    I eventually learnt my lesson, but I was able to adapt my language. That
    isn't always the case.


    Actually, ranges of about ten levels seem to be not uncommon amongst programming languages to provide a sensible, widely accepted grouping. Language designers seem to be trying to avoid a flood of unnecessary parentheses in programs.

    I use 5 levels where C uses ten (from multiply to ||).

    Parentheses used to override default precedence only occur about once
    per 100 lines of code in my codebases. That is very rare.

    I can't give reliable figures for C, as measured by my compiler, as they
    can be affected by macro expansions for example that inject parentheses everywhere. But then C source is awash with parentheses anyway.


    And here's a precedence table for another language that facilitates
    that there's no parenthesis at all necessary to obtain unambiguous expressions:

       lvl  op
      ---------
         1    !!
         2    !§
         3    !$
    ...
        61    =/
        62    =+
        63    =~
        64    ==


    And here a variant with only one level of operator precedence,
    all listed in a single group[*]

       !! !§ !$ !% !/ !+ !~ != §! §§ §$ §% §/ §+ §~ §=
       $! $§ $$ $% $/ $+ $~ $= %! %§ %$ %% %/ %+ %~ %=
       /! /§ /$ /% // /+ /~ /= +! +§ +$ +% +/ ++ +~ +=
       ~! ~§ ~$ ~% ~/ ~+ ~~ ~= =! =§ =$ =% =/ =+ =~ ==

    OK. I've no idea what your point is, or what all these mean.

    The first language I implemented had no operator precedences and needed
    no table. Expressions were unambiguous.

    It was a lot more usable than this.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From James Kuyper@jameskuyper@alumni.caltech.edu to comp.lang.c on Sun May 17 20:43:51 2026
    From Newsgroup: comp.lang.c

    On 2026-05-13 13:48, Bart wrote:
    Bart <bc@freeuk.com> writes:

    The one for the ?: operator is particularly obscure, so in an
    expression like one of these:

        a + b ? c - d : e * f
        a ? b ? c : d ? e : f : g

    [...]

    The lines are not meant to mean anything, just sequences of terms and operators. You can think of them as exercises where you add parentheses
    to make them unambiguous.

    What I think you mean is that the parenthesis help those who are
    unfamiliar with the relevant rules understand what those rules already unambiguously require.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From James Kuyper@jameskuyper@alumni.caltech.edu to comp.lang.c on Mon May 18 19:48:07 2026
    From Newsgroup: comp.lang.c

    On 2026-05-14 13:32, Bart wrote:
    ...
    In the case if C, it also decided that ?: belongs in this chart of /
    binary/ operators. (I supposed you can consider each of ? and : as a
    binary operator...)

    When and where was that decided? There's a big difference between
    putting ?: in a chart along with binary and unary operators (which
    happened in section 2.12 of the 1st edition of K&R) and putting it in a
    chart of binary operators. To the best of my knowledge, the latter never happened. Could you please identify where it did?
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Bart@bc@freeuk.com to comp.lang.c on Tue May 19 01:12:06 2026
    From Newsgroup: comp.lang.c

    On 19/05/2026 00:48, James Kuyper wrote:
    On 2026-05-14 13:32, Bart wrote:
    ...
    In the case if C, it also decided that ?: belongs in this chart of /
    binary/ operators. (I supposed you can consider each of ? and : as a
    binary operator...)

    When and where was that decided? There's a big difference between
    putting ?: in a chart along with binary and unary operators (which
    happened in section 2.12 of the 1st edition of K&R) and putting it in a
    chart of binary operators. To the best of my knowledge, the latter never happened. Could you please identify where it did?

    If you read my post again, you'll find that 'this chart' most likely
    refers to my suggested chart containing those 4 groups I mentioned.

    That chart contains a set of binary (and infix) operators that also
    appear in K&R2. I'm saying that whoever put that together in K&R2
    decided that ?: belonged in this set.

    (Personally I don't, as I don't consider a ?:-like feature to be an
    operator, but even it it was, a 3-way operator is a poor fit when all
    the others are 2-way.)
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@Keith.S.Thompson+u@gmail.com to comp.lang.c on Mon May 18 19:22:08 2026
    From Newsgroup: comp.lang.c

    Bart <bc@freeuk.com> writes:
    [...]
    If you read my post again, you'll find that 'this chart' most likely
    refers to my suggested chart containing those 4 groups I mentioned.

    That chart contains a set of binary (and infix) operators that also
    appear in K&R2. I'm saying that whoever put that together in K&R2
    decided that ?: belonged in this set.

    The ?: operator, which is a ternary operator, belongs in the set
    of operators.

    You somehow concluded that ?: was being treated as a binary operator.
    It very very clearly is not a binary operator. The chart in K&R2
    very very clearly does not imply that it is.

    (Personally I don't, as I don't consider a ?:-like feature to be an
    operator,

    It is an operator in C.

    but even it it was, a 3-way operator is a poor fit when all
    the others are 2-way.)

    No, not all the others are 2-way.

    Are you now saying that you think ?: *should* be a binary (2-way)
    operator? (I'm not going to ask how that would work.)
    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.c on Tue May 19 10:12:34 2026
    From Newsgroup: comp.lang.c

    On 2026-05-11 22:29, Bart wrote:
    On 11/05/2026 20:06, Waldek Hebisch wrote:

    [...]  But now hackers from
    hostile country can break critical systems (shut down
    electricity in whole county, destroy electric plants, stop
    vital pipeline from operationg, etc) and goverments got
    more serious.

    Can they do that; generally? - My experience is that it depends
    on who has done, and who is accountable for the systems setups.
    And it depends on the requested and applied national standards.

    [...]

    With these hackers, why are critical systems connected to the public internet in the first place?

    Good question; for those systems where that is the case.

    The reality looks different. Or, rather; it depends on where you
    look into. (Our country is very keen of its security standards.)

    But then, there's also critical infrastructure that is inherently
    "connected to the public internet", for example because its task
    is no connect the public or provide public services.

    Nuclear plants (and other critical infrastructure) certainly don't
    need their _control system_ be "connected to the public internet".
    There's applied and long existing security concepts established.

    Alas, contemporary IT-systems' evolution seems to start disrespect
    such long existing expertise and wisdom. The good thing is, though,
    that there's still instances who have a close look at the evolution.

    Janis

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.c on Tue May 19 10:40:55 2026
    From Newsgroup: comp.lang.c

    On 2026-05-19 10:12, Janis Papanagnou wrote:
    On 2026-05-11 22:29, Bart wrote:
    On 11/05/2026 20:06, Waldek Hebisch wrote:

    [...]  But now hackers from
    hostile country can break critical systems (shut down
    electricity in whole county, destroy electric plants, stop
    vital pipeline from operationg, etc) and goverments got
    more serious.

    Can they do that; generally? - My experience is that it depends
    on who has done, and who is accountable for the systems setups.
    And it depends on the requested and applied national standards.

    [...]

    With these hackers, why are critical systems connected to the public
    internet in the first place?

    Good question; for those systems where that is the case.

    The reality looks different. Or, rather; it depends on where you
    look into. (Our country is very keen of its security standards.)

    But then, there's also critical infrastructure that is inherently
    "connected to the public internet", for example because its task
    is no connect the public or provide public services.

    Typo (crucially changing semantics):

    "[...] for example because its task
    is to connect the public or provide public services."


    Nuclear plants (and other critical infrastructure) certainly don't
    need their _control system_ be "connected to the public internet".
    There's applied and long existing security concepts established.

    Alas, contemporary IT-systems' evolution seems to start disrespect
    such long existing expertise and wisdom. The good thing is, though,
    that there's still instances who have a close look at the evolution.

    Janis


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Bart@bc@freeuk.com to comp.lang.c on Tue May 19 11:31:50 2026
    From Newsgroup: comp.lang.c

    On 19/05/2026 03:22, Keith Thompson wrote:
    Bart <bc@freeuk.com> writes:
    [...]
    If you read my post again, you'll find that 'this chart' most likely
    refers to my suggested chart containing those 4 groups I mentioned.

    That chart contains a set of binary (and infix) operators that also
    appear in K&R2. I'm saying that whoever put that together in K&R2
    decided that ?: belonged in this set.

    The ?: operator, which is a ternary operator, belongs in the set
    of operators.

    Do we really want to get this pedantic and discuss the intent of every
    single choice of word I've made?

    Say I'm talking about this set: "+ - * /", binary/infix operators
    (ignore that 3 of them also unary/prefix).

    This same set is part of the table of 1/2/3-way 'operators' used in K&R2.

    I'd remarked that K&R put the ?: 3-way operator amongst the section of
    the table which is full of 2-way ops (with the 1-way ops sharing the top
    two tiers) and idly speculated whether the '?' and ':' parts of '?:'
    were being treated as though each was a 2-way operator.


    You somehow concluded that ?: was being treated as a binary operator.
    It very very clearly is not a binary operator. The chart in K&R2
    very very clearly does not imply that it is.

    (Personally I don't, as I don't consider a ?:-like feature to be an
    operator,

    It is an operator in C.

    but even it it was, a 3-way operator is a poor fit when all
    the others are 2-way.)

    No, not all the others are 2-way.

    Are you now saying that you think ?: *should* be a binary (2-way)
    operator? (I'm not going to ask how that would work.

    This is the question *I'm* asking! How does a 3-way operator work in
    that set-up? Is it still called 'infix'?

    But is seems like nobody is obliged to answer that because the C
    standard defines it all as syntax anyway, and just happens to use the
    word 'operator' to refer to all the bit of syntax that occur between the terminals of any expression.

    Even though this is a poor fit for those like "[]", "()", "?:" and "(T)".


    (FWIW, here is a simplified subset of an informal grammar that applies
    to my languages; 'unit' is a statement or expression, but only
    expression-like terms are listed:

    unit = term {op / ':=' / '..' term}*

    term = name
    = intconst
    = realconst
    = charconst
    = stringconst
    = op term # prefix unary op
    = term op # postfix unary op
    = term '.' name # member selection
    = '(' unit ')'
    = term '^' # deref
    = '&' term
    = term '(' unit|',' ')' # function call
    = typespec '(' unit ')' # cast
    = term '[' unit|',' ']' # indexing
    = term '.' property
    = Etc

    ( {...}* repeats zero or more times; '/' separates choices, as does '=';
    a|b means zero or more 'a' separated by b.)

    Notice that [], (), pointer deref, casts, and various other bits have
    their own productions.

    'op' is one of a common pool of operator names. Not all are allowed in
    any one context, but that is not specified here; the parser will detect
    those that are not appropriate. This is not a formal grammar that can be
    used to drive an automatic tool. It is for a human.

    BTW here are two more lines:

    = '(' unit '|' unit '|' unit ')' # 3-way select
    = '(' unit '|' unit|, '|' unit ')' # N-way select

    The first is equivalent to C's ?: feature.)


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From antispam@antispam@fricas.org (Waldek Hebisch) to comp.lang.c on Tue May 19 12:21:12 2026
    From Newsgroup: comp.lang.c

    Bart <bc@freeuk.com> wrote:
    On 19/05/2026 03:22, Keith Thompson wrote:
    Bart <bc@freeuk.com> writes:
    <snip>
    Say I'm talking about this set: "+ - * /", binary/infix operators
    (ignore that 3 of them also unary/prefix).

    This same set is part of the table of 1/2/3-way 'operators' used in K&R2.

    I'd remarked that K&R put the ?: 3-way operator amongst the section of
    the table which is full of 2-way ops (with the 1-way ops sharing the top
    two tiers) and idly speculated whether the '?' and ':' parts of '?:'
    were being treated as though each was a 2-way operator.


    You somehow concluded that ?: was being treated as a binary operator.
    It very very clearly is not a binary operator. The chart in K&R2
    very very clearly does not imply that it is.

    (Personally I don't, as I don't consider a ?:-like feature to be an
    operator,

    It is an operator in C.

    but even it it was, a 3-way operator is a poor fit when all
    the others are 2-way.)

    No, not all the others are 2-way.

    Are you now saying that you think ?: *should* be a binary (2-way)
    operator? (I'm not going to ask how that would work.

    This is the question *I'm* asking! How does a 3-way operator work in
    that set-up? Is it still called 'infix'?
    <snip>
    Even though this is a poor fit for those like "[]", "()", "?:" and "(T)".

    In late sixties there were concept of "operator precedence grammar"
    and related parsing technology. Basicaly, I you wanted systematic
    way of parsing there was operator precedence or recursive descent,
    otherwise it was more or less ad hoc. In operator precedence
    grammar most "interesting" things were operators of varying arity.

    If you ask "how does it work?", the answer is that parsers using
    that where shift-reduce parsers and priorities are used to choose
    between shift and reduce actions. People also realised to
    operator precedence can be used together with recursive descent,
    leading to small and efficient parsers handling rich language.
    Operator precedence alone puts restrictions on the language
    (but there were languages specially designed to be parsed using
    operator precedence), recursive descent alows more general
    languages, but gets messy on constructs well handled by operator
    precedence. AFAIK first C compiler used combination of operator
    precedence and recursive descent, and for some time there was a
    belief that correct and full BNF for C was impossible to give or
    too messy. Current gramamr only appeared during ANSI process.
    --
    Waldek Hebisch
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Bart@bc@freeuk.com to comp.lang.c on Tue May 19 14:15:09 2026
    From Newsgroup: comp.lang.c

    On 19/05/2026 13:21, Waldek Hebisch wrote:
    Bart <bc@freeuk.com> wrote:
    On 19/05/2026 03:22, Keith Thompson wrote:
    Bart <bc@freeuk.com> writes:
    <snip>
    Say I'm talking about this set: "+ - * /", binary/infix operators
    (ignore that 3 of them also unary/prefix).

    This same set is part of the table of 1/2/3-way 'operators' used in K&R2.

    I'd remarked that K&R put the ?: 3-way operator amongst the section of
    the table which is full of 2-way ops (with the 1-way ops sharing the top
    two tiers) and idly speculated whether the '?' and ':' parts of '?:'
    were being treated as though each was a 2-way operator.


    You somehow concluded that ?: was being treated as a binary operator.
    It very very clearly is not a binary operator. The chart in K&R2
    very very clearly does not imply that it is.

    (Personally I don't, as I don't consider a ?:-like feature to be an
    operator,

    It is an operator in C.

    but even it it was, a 3-way operator is a poor fit when all >>>> the others are 2-way.)

    No, not all the others are 2-way.

    Are you now saying that you think ?: *should* be a binary (2-way)
    operator? (I'm not going to ask how that would work.

    This is the question *I'm* asking! How does a 3-way operator work in
    that set-up? Is it still called 'infix'?
    <snip>
    Even though this is a poor fit for those like "[]", "()", "?:" and "(T)".

    In late sixties there were concept of "operator precedence grammar"
    and related parsing technology. Basicaly, I you wanted systematic
    way of parsing there was operator precedence or recursive descent,
    otherwise it was more or less ad hoc. In operator precedence
    grammar most "interesting" things were operators of varying arity.

    If you ask "how does it work?", the answer is that parsers using
    that where shift-reduce parsers and priorities are used to choose
    between shift and reduce actions. People also realised to
    operator precedence can be used together with recursive descent,
    leading to small and efficient parsers handling rich language.
    Operator precedence alone puts restrictions on the language
    (but there were languages specially designed to be parsed using
    operator precedence), recursive descent alows more general
    languages, but gets messy on constructs well handled by operator
    precedence. AFAIK first C compiler used combination of operator
    precedence and recursive descent, and for some time there was a
    belief that correct and full BNF for C was impossible to give or
    too messy. Current gramamr only appeared during ANSI process.

    I think it's still a little messy!

    Compare with the example of mine that I gave. Although that off-loads
    some things to the parser, like precedence, which is notionally
    table-driven.

    However I understand the importance of clear presentation. Half of the C grammar reminds me of the 'twisty little passages, all alike' section of Colossal Adventure.

    Why would they choose such long terms that are so confusedly alike?

    Note that in C, expression structure has to be handled twice: in the proprocessor, and in the main language.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From James Kuyper@jameskuyper@alumni.caltech.edu to comp.lang.c on Tue May 19 11:31:48 2026
    From Newsgroup: comp.lang.c

    Bart <bc@freeuk.com> writes:
    [Add attribution]
    On 2026-05-18 19:48, James Kuyper wrote:
    [Restore snippage]
    On 2026-05-14 13:32, Bart wrote:
    ...
    In the case if C, it also decided that ?: belongs in this chart of /
    binary/ operators. (I supposed you can consider each of ? and : as a
    binary operator...)
    [End restored snippage]
    [...]
    If you read my post again, you'll find that 'this chart' most likely
    refers to my suggested chart containing those 4 groups I mentioned.

    That chart contains a set of binary (and infix) operators that also
    appear in K&R2. I'm saying that whoever put that together in K&R2
    decided that ?: belonged in this set.
    That table is preceded by the following description: "The table below summarizes the rules for precedence and associativity of all operators, including those which we have not yet discussed".

    How can you read "all operators" and reach the conclusion that it's only supposed to contain the binary operators? Furthermore, K&R explicitly
    describes ?: as a ternary operator, not a binary one.

    In particular, that table includes, () [] -> . ! ~ ++ -- (type) sizeof
    and the unary versions of - * &. By the same logic you're using, "C also decided" to put all of those operator in a chart of binary operators.

    The C standard identifies (), [], ->, and . as parts of postfix
    expressions. Personally, the last three seem to me to be infix
    operators, as you say. It identifies the others listed above as unary,
    which seems entirely correct.


    (Personally I don't, as I don't consider a ?:-like feature to be an
    operator,

    You have a right to your opinion, But the C standard explicitly labels
    it as the conditional operator.
    The C standard contains no explicit definition of "operator", just a
    long list of individual things that it describes as operators. However,
    it also contains a few statements that apply to all operators. Operators
    are supposed to have operands - ?: has three. Expressions are made up of operators and their operands. C would be very weird if a ? b : c failed
    to qualify as an expression because ?: did not qualify as an operator.

    but even it it was, a 3-way operator is a poor fit when all
    the others are 2-way.)

    It's as good a fit as any of the unary operators. They all fit because
    it's a table of ALL operators, not just binary ones.

    You've expressed the opinion that unary operators don't belong in a
    precedence table. In a sense, the C standard agrees with you. It doesn't
    put them in a precedence table. That's because it doesn't put anything
    in a precedence table.
    However, in K&R, the fact that the unary operators are in the second row
    of the precedence table is what makes it clear that *p+1 means (*p)+1,
    and not *(p+1). Why would you consider that unimportant? In the C
    standard, that same information is conveyed by the grammar, rather than
    a precedence table.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@Keith.S.Thompson+u@gmail.com to comp.lang.c on Tue May 19 14:12:32 2026
    From Newsgroup: comp.lang.c

    Bart <bc@freeuk.com> writes:
    On 19/05/2026 03:22, Keith Thompson wrote:
    Bart <bc@freeuk.com> writes:
    [...]
    If you read my post again, you'll find that 'this chart' most likely
    refers to my suggested chart containing those 4 groups I mentioned.

    That chart contains a set of binary (and infix) operators that also
    appear in K&R2. I'm saying that whoever put that together in K&R2
    decided that ?: belonged in this set.

    The ?: operator, which is a ternary operator, belongs in the set
    of operators.

    Do we really want to get this pedantic and discuss the intent of every
    single choice of word I've made?

    Say I'm talking about this set: "+ - * /", binary/infix operators
    (ignore that 3 of them also unary/prefix).

    I think of unary "-" and binary "-" as two distinct operators
    that happen to use the same symbol. The grammar is carefully
    designed to avoid any ambiguity; each "-" symbol in an expression
    is unambiguously one or the other.

    This same set is part of the table of 1/2/3-way 'operators' used in K&R2.

    I'd remarked that K&R put the ?: 3-way operator amongst the section of
    the table which is full of 2-way ops (with the 1-way ops sharing the
    top two tiers) and idly speculated whether the '?' and ':' parts of
    '?:' were being treated as though each was a 2-way operator.

    And that's not a useful way to look at it.

    I think what you're saying is that you want to have 4 separate
    operator precedence tables, one each for unary, postfix, binary,
    and ternary operators (or something like that). But that doesn't
    work well because the language's only ternary operator, "?:",
    has a precedence between "||" and the assignment operators.
    Pretending that "?:" is somehow binary reminds me of Ptolemy's
    epicycles, an added complication that tries to solve a problem
    that's better solved by rethinking the whole structure.

    My conclusion is that having separate tables for the different kinds
    of operators is not a feasible approach, and it was never a good
    idea in the first place. Table 2-1 in K&R2 is less than a single
    page, and I find it quite clear. You're tying yourself in knots
    trying to find a way to use a poor approach that is inconsistent
    with the way C's expression syntax is defined.

    [...]

    This is the question *I'm* asking! How does a 3-way operator work in
    that set-up? Is it still called 'infix'?

    A 3-way operator *doesn't* work in "that set-up". I conclude that
    "that set-up" is a poor fit for C's expression grammar.

    [...]
    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@Keith.S.Thompson+u@gmail.com to comp.lang.c on Tue May 19 14:14:14 2026
    From Newsgroup: comp.lang.c

    Bart <bc@freeuk.com> writes:
    [...]
    I think it's still a little messy!

    Yes, C's expression grammar is a little messy. We're in complete
    agreement on that point.

    [...]
    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From James Kuyper@jameskuyper@alumni.caltech.edu to comp.lang.c on Tue May 19 19:00:50 2026
    From Newsgroup: comp.lang.c

    Bart <bc@freeuk.com> writes:
    ...
    This is the question *I'm* asking! How does a 3-way operator work in
    that set-up?

    It doesn't - which is why the C standard uses grammar rules rather that precedence and associativity tables to define how ?: (and all other
    operators) works.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@Keith.S.Thompson+u@gmail.com to comp.lang.c on Tue May 19 16:56:21 2026
    From Newsgroup: comp.lang.c

    James Kuyper <jameskuyper@alumni.caltech.edu> writes:
    Bart <bc@freeuk.com> writes:
    ...
    This is the question *I'm* asking! How does a 3-way operator work in
    that set-up?

    It doesn't - which is why the C standard uses grammar rules rather that precedence and associativity tables to define how ?: (and all other operators) works.

    And it's why the precedence table in K&R2 shows *all* the operators,
    including the ternary "?:" operator that happens to be preceded and
    followed by binary operators. It's only a problem if you insist,
    for some reason, on having a table that shows only binary operators.
    (K&R1 has a nearly identical table, differing only in that C didn't
    yet have unary "+" and the K&R2 table lists all the assigment
    operators.)
    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.c on Wed May 20 04:20:02 2026
    From Newsgroup: comp.lang.c

    On 2026-05-19 23:12, Keith Thompson wrote:
    Bart <bc@freeuk.com> writes:
    [...]

    And that's not a useful way to look at it.

    I think what you're saying is that you want to have 4 separate
    operator precedence tables, one each for unary, postfix, binary,
    and ternary operators (or something like that). But that doesn't
    work well because the language's only ternary operator, "?:",
    has a precedence between "||" and the assignment operators.

    Pretending that "?:" is somehow binary reminds me of Ptolemy's
    epicycles, an added complication that tries to solve a problem
    that's better solved by rethinking the whole structure.

    Since you mention Ptolemy...


    [...] You're tying yourself in knots
    trying to find a way to use a poor approach that is inconsistent
    with the way C's expression syntax is defined.

    ...we might as well hint to how Alexander the Great solved that
    Gordian knot, given that Bart seems to be hopelessly entangled
    in his mental knots.

    (It's his responsibility to solve his entanglement, not ours.)

    Janis

    [...]
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Tim Rentsch@tr.17687@z991.linuxsc.com to comp.lang.c on Fri May 22 21:58:26 2026
    From Newsgroup: comp.lang.c

    antispam@fricas.org (Waldek Hebisch) writes:

    [...] for some time there was a belief that correct and full BNF
    for C was impossible to give or too messy.

    I find this statement hard to believe. There is nothing especially
    difficult about a syntax for the C language. There is of course the
    well-known problem with typedef names, but that has long been
    understood to be unresolvable in any context-free way (and so cannot
    be dealt with in BNF). Earlier versions of C (pre-K&R) had other
    syntax for some constructs, and maybe that was the issue. I'm at a
    loss to understand how people could have thought a BNF for C, for
    the post K&R version of the language, would be challenging or
    difficult.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@Keith.S.Thompson+u@gmail.com to comp.lang.c on Fri May 22 23:23:17 2026
    From Newsgroup: comp.lang.c

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
    antispam@fricas.org (Waldek Hebisch) writes:
    [...] for some time there was a belief that correct and full BNF
    for C was impossible to give or too messy.

    I find this statement hard to believe. There is nothing especially
    difficult about a syntax for the C language. There is of course the well-known problem with typedef names, but that has long been
    understood to be unresolvable in any context-free way (and so cannot
    be dealt with in BNF). Earlier versions of C (pre-K&R) had other
    syntax for some constructs, and maybe that was the issue. I'm at a
    loss to understand how people could have thought a BNF for C, for
    the post K&R version of the language, would be challenging or
    difficult.

    I'm having trouble figuring out what you mean here. You acknowledge
    that typedefs make a full BNF grammar for C impossible, and then
    you say that it's not challenging or difficult.

    I'm aware that there are workarounds, basically treating typedef
    names a context-dependent keywords.
    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Tim Rentsch@tr.17687@z991.linuxsc.com to comp.lang.c on Sat May 23 00:09:56 2026
    From Newsgroup: comp.lang.c

    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

    antispam@fricas.org (Waldek Hebisch) writes:

    [...] for some time there was a belief that correct and full BNF
    for C was impossible to give or too messy.

    I find this statement hard to believe. There is nothing especially
    difficult about a syntax for the C language. There is of course the
    well-known problem with typedef names, but that has long been
    understood to be unresolvable in any context-free way (and so cannot
    be dealt with in BNF). Earlier versions of C (pre-K&R) had other
    syntax for some constructs, and maybe that was the issue. I'm at a
    loss to understand how people could have thought a BNF for C, for
    the post K&R version of the language, would be challenging or
    difficult.

    I'm having trouble figuring out what you mean here. You acknowledge
    that typedefs make a full BNF grammar for C impossible, and then
    you say that it's not challenging or difficult.

    Because I think the problem with typedef names is orthogonal to
    what Waldek was saying. The problem with typedef names is not
    solvable in a context-free grammar, and that is just as true today
    as it was 50 years ago. The syntax I am talking about is C syntax
    without regard to the problem with typedef names.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@Keith.S.Thompson+u@gmail.com to comp.lang.c on Sat May 23 04:13:00 2026
    From Newsgroup: comp.lang.c

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
    antispam@fricas.org (Waldek Hebisch) writes:
    [...] for some time there was a belief that correct and full BNF
    for C was impossible to give or too messy.

    I find this statement hard to believe. There is nothing especially
    difficult about a syntax for the C language. There is of course the
    well-known problem with typedef names, but that has long been
    understood to be unresolvable in any context-free way (and so cannot
    be dealt with in BNF). Earlier versions of C (pre-K&R) had other
    syntax for some constructs, and maybe that was the issue. I'm at a
    loss to understand how people could have thought a BNF for C, for
    the post K&R version of the language, would be challenging or
    difficult.

    I'm having trouble figuring out what you mean here. You acknowledge
    that typedefs make a full BNF grammar for C impossible, and then
    you say that it's not challenging or difficult.

    Because I think the problem with typedef names is orthogonal to
    what Waldek was saying. The problem with typedef names is not
    solvable in a context-free grammar, and that is just as true today
    as it was 50 years ago. The syntax I am talking about is C syntax
    without regard to the problem with typedef names.

    I still don't understand your point. A "C syntax without regard
    to the problem with typedef names" would not be a correct C syntax
    (unless it's for a pre-typedef version of the language).

    Typedef names aren't a huge problem, but they're something that has
    to be dealt with in a non-trivial way if you want to use something
    close to a BNF grammar.

    When I read Waldek's statement that "and for some time there was a
    belief that correct and full BNF for C was impossible to give or
    too messy", I assumed that the typedef issue was exactly what he
    was talking about. Perhaps I was mistaken, but I don't know of
    any other reason to think that a full BNF for C would be thought
    to be impossible, and I think you're saying you don't know of any
    such reason either.

    Whatever Waldek meant, I think you and I are in agreement that (a)
    a full BNF grammar for C is impossible because of the typedef issue,
    but (b) the typedef issue can be worked around without too much
    difficulty, using something reasonably close to a full BNF grammar.
    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Tim Rentsch@tr.17687@z991.linuxsc.com to comp.lang.c on Sun May 24 04:37:36 2026
    From Newsgroup: comp.lang.c

    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

    antispam@fricas.org (Waldek Hebisch) writes:

    [...] for some time there was a belief that correct and full BNF
    for C was impossible to give or too messy.

    I find this statement hard to believe. There is nothing especially
    difficult about a syntax for the C language. There is of course the
    well-known problem with typedef names, but that has long been
    understood to be unresolvable in any context-free way (and so cannot
    be dealt with in BNF). Earlier versions of C (pre-K&R) had other
    syntax for some constructs, and maybe that was the issue. I'm at a
    loss to understand how people could have thought a BNF for C, for
    the post K&R version of the language, would be challenging or
    difficult.

    I'm having trouble figuring out what you mean here. You acknowledge
    that typedefs make a full BNF grammar for C impossible, and then
    you say that it's not challenging or difficult.

    Because I think the problem with typedef names is orthogonal to
    what Waldek was saying. The problem with typedef names is not
    solvable in a context-free grammar, and that is just as true today
    as it was 50 years ago. The syntax I am talking about is C syntax
    without regard to the problem with typedef names.

    I still don't understand your point. [...]

    Yes, I can see that.

    By the way, it wasn't a point, it was only an explanation. I'm
    sorry that it wasn't more understandable for you.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@Keith.S.Thompson+u@gmail.com to comp.lang.c on Wed May 27 17:57:10 2026
    From Newsgroup: comp.lang.c

    antispam@fricas.org (Waldek Hebisch) writes:
    [...]
    If you ask "how does it work?", the answer is that parsers using
    that where shift-reduce parsers and priorities are used to choose
    between shift and reduce actions. People also realised to
    operator precedence can be used together with recursive descent,
    leading to small and efficient parsers handling rich language.
    Operator precedence alone puts restrictions on the language
    (but there were languages specially designed to be parsed using
    operator precedence), recursive descent alows more general
    languages, but gets messy on constructs well handled by operator
    precedence. AFAIK first C compiler used combination of operator
    precedence and recursive descent, and for some time there was a
    belief that correct and full BNF for C was impossible to give or
    too messy. Current gramamr only appeared during ANSI process.

    You say that it was believed that a full BNF for C was "impossible
    to give or too messy". Can you expand on that and/or provide
    a citation?

    The only problem in that area that I'm aware of is "typedef",
    but that was a later addition (some time between 1975 and 1978).

    What exactly did you mean?
    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2