• Re: Taming The Switch-Statement

    From cross@[email protected] (Dan Cross) to comp.lang.c on Tue Oct 13 20:52:04 2026
    From Newsgroup: comp.lang.c

    In article <11alkqa$4o6l$[email protected]>,
    Janis Papanagnou <[email protected]> wrote:
    On 2026-10-13 16:38, Dan Cross wrote:
    In article <11al8uc$hk7a$[email protected]>, bart <[email protected]> wrote:
    [snip]
    So your workaround had an error. That's what happens.

    I could foresee such a stupid response! - You're a hopeless case.
    Given that you've had even stupid syntax errors in your original
    code I'm astonished that you even dare to get into such argument.


    There is no programming that prevents all errors.

    (That was not even programming; it was a quick write down for the
    post as an example structure to explain what's to be visualized.)


    [snip]
    Jesus. I take it that you don't agree it is a hack then?

    Writing a loop with a predicate that is composed by an 'and' is
    certainly not a "hack" but usual programming. Nowadays you learn
    such things in kindergarten.

    Were you referring to me, Janis? Or to bart?

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Tue Oct 13 22:24:20 2026
    From Newsgroup: comp.lang.c

    On 13/10/2026 21:52, Dan Cross wrote:
    In article <11alkqa$4o6l$[email protected]>,
    Janis Papanagnou <[email protected]> wrote:
    On 2026-10-13 16:38, Dan Cross wrote:
    In article <11al8uc$hk7a$[email protected]>, bart <[email protected]> wrote: >>>> [snip]
    So your workaround had an error. That's what happens.

    I could foresee such a stupid response! - You're a hopeless case.
    Given that you've had even stupid syntax errors in your original
    code I'm astonished that you even dare to get into such argument.


    There is no programming that prevents all errors.

    (That was not even programming; it was a quick write down for the
    post as an example structure to explain what's to be visualized.)


    [snip]
    Jesus. I take it that you don't agree it is a hack then?

    Writing a loop with a predicate that is composed by an 'and' is
    certainly not a "hack" but usual programming. Nowadays you learn
    such things in kindergarten.

    Were you referring to me, Janis? Or to bart?
    If there's any insult implied then it will have been me.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@[email protected] to comp.lang.c on Tue Oct 13 21:54:06 2026
    From Newsgroup: comp.lang.c

    On Tue, 13 Oct 2026 07:23:40 -0000 (UTC), Waldek Hebisch wrote:

    So what those counts indicate: majority of loops is simple, that is
    have no early exit. Vast majority of early exits is done via
    'return'.

    My experience in my own C code is quite the opposite. Lots of loops
    have exits in the middle, leading me to use forms like “for (;;)”. I
    also try to avoid putting “return” anywhere other than the end of a function, to make it easier to see the flow of control.

    *cough* Nassi-Shneiderman diagrams *cough*
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@[email protected] to comp.lang.c,comp.lang.python on Tue Oct 13 22:00:41 2026
    From Newsgroup: comp.lang.c

    On Sat, 10 Oct 2026 00:25:54 -0000 (UTC), I wrote:

    For comparison, here is an example of Python’s match-statement. Like
    all the good (i.e. non-C-based) designs, the designers saw no point
    in having fall-through.

    This is a very simple example, involving straight matching of values
    against instances of an enum. There are also more complex
    pattern-matching options available.

    Another, slightly more involved example, where the matching is against
    the components of a tuple. This is from a parser for the Varlink
    interface definition language. Note the use of the “_” wildcard to
    indicate don’t-care parts of matches:

    match token.value, token.rule_name :
    case "[]", _ :
    nexttoken()
    valtype = parse_typedef(None)
    result = ArrayType(name, valtype)
    case "[string]", _ :
    nexttoken()
    valtype = parse_typedef(None)
    result = DictType(name, valtype)
    case _, "elttypedef" :
    result = parse_elttypedef(name)
    case _, "typedef" :
    result = parse_typedef(name)
    case _ :
    raise AssertionError \
    (
    "unrecognized typedef token %s: %s"
    %
    (token.rule_name, repr(token.value))
    )
    #end match
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@[email protected] to comp.lang.c on Wed Oct 14 00:03:21 2026
    From Newsgroup: comp.lang.c

    On 2026-10-13 22:52, Dan Cross wrote:

    Were you referring to me, Janis? Or to bart?

    You can identify the association of the answers by its attribution
    indent level. - Most was attributed to bart's text that was quoted.

    The only part that was attributed to what you said was this:

    Dan wrote:

    There is no programming that prevents all errors.

    I commented that, in parenthesis (i.e. just as a side remark):

    (That was not even programming; it was a quick write down for the
    post as an example structure to explain what's to be visualized.)

    Bart perceived my program text as a "programming error", I explained
    that it was just a sloppy "Usenet-posting writing error".

    Of course programming errors can happen. As can writing errors happen.

    Given his text in your post gave the impression that he considers my
    sloppy code-writing in my post as a problem of the technical language
    design of "C"; it wasn't, IMO. - That was all I tried to communicate.

    While we seem to have a different view on whether the C-code is to be considered a "hack" (or as I see it, just typical programming) I didn't
    think that this difference in views is worth discussing since that's
    just (our personal) opinions.

    Janis

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Tue Oct 13 23:19:00 2026
    From Newsgroup: comp.lang.c

    On 13/10/2026 23:00, Lawrence D’Oliveiro wrote:
    On Sat, 10 Oct 2026 00:25:54 -0000 (UTC), I wrote:

    For comparison, here is an example of Python’s match-statement. Like
    all the good (i.e. non-C-based) designs, the designers saw no point
    in having fall-through.

    This is a very simple example, involving straight matching of values
    against instances of an enum. There are also more complex
    pattern-matching options available.

    Another, slightly more involved example, where the matching is against
    the components of a tuple. This is from a parser for the Varlink
    interface definition language. Note the use of the “_” wildcard to indicate don’t-care parts of matches:

    match token.value, token.rule_name :
    case "[]", _ :
    nexttoken()
    valtype = parse_typedef(None)
    result = ArrayType(name, valtype)
    case "[string]", _ :
    nexttoken()
    valtype = parse_typedef(None)
    result = DictType(name, valtype)
    case _, "elttypedef" :
    result = parse_elttypedef(name)
    case _, "typedef" :
    result = parse_typedef(name)
    case _ :
    raise AssertionError \
    (
    "unrecognized typedef token %s: %s"
    %
    (token.rule_name, repr(token.value))
    )
    #end match

    This is not quite structural pattern matching. Isn't this just
    equivalent to:

    match token.value:
    case "[]":
    nexttoken()
    valtype = parse_typedef(None)
    result = ArrayType(name, valtype)
    case "[string]":
    nexttoken()
    valtype = parse_typedef(None)
    result = DictType(name, valtype)
    else:
    match token.rule_name:
    case "elttypedef":
    result = parse_elttypedef(name)
    case "typedef":
    result = parse_typedef(name)
    else
    .... error

    Except that 'else' probably doesn't work like this (why not).


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Wed Oct 14 00:21:00 2026
    From Newsgroup: comp.lang.c

    On 13/10/2026 01:33, Keith Thompson wrote:
    bart <[email protected]> writes:
    [...]
    This is my first example expressed in C (note those first three args
    are passed by reference):

    while (pmtype = nextcmdparam(&paramno, &name, &value, "m") {
    switch (pmtype)
    case pm_option: ...; break;
    case pm_sourcefile:
    if (passlevel == run_pass || passlevel == runpcl_pass) {
    break;

    Except I can't use break like that. So I have to find a workaround.

    The code appears to be valid C that doesn't do what you want. I can't
    easily tell what you want it to do. I don't know which of the two break statements was intended to break out of the loop. A comment would have solved that.

    I'm going to guess that the first break is supposed to apply to the
    switch statement, and the second to the while loop.

    You want the language to be changed to make this kind of thing easier.

    That's already happening. If you take a look at the N3886 working
    draft for C2y, it has named break statements. In C2y (or in gcc
    if you use an extension), the above could be written as:

    WHILE:
    while (pmtype = nextcmdparam(&paramno, &name, &value, "m") {
    SWITCH:
    switch (pmtype)
    case pm_option: ...; break SWITCH;
    case pm_sourcefile:
    if (passlevel == run_pass || passlevel == runpcl_pass) {
    break WHILE;

    assuming it's the second "break' that's supposed to break out of
    the loop. (I'd probably use more meaninful names.)

    There is already a solution for the problem you're complaining about.
    (It also solves the problem of breaking out of nested loops.)

    If you're unable to use this feature, you can use goto. That's not
    ideal, but with well chosen label names and no backward branching
    it's not too bad.

    I've got a better idea. I added an extra keyword to my C compiler called "breakloop". It's like 'break' but always works with the nearest
    enclosing loop, even from inside switch.

    So this example (a starts at 0):

    while (1) {
    switch (a++) {
    case 1: puts("one"); break;
    case 2: puts("two"); breakloop;
    case 3: puts("three"); break;
    default: puts("other");
    }

    if (a>40) break;
    }

    finishes after displaying 'two', instead of after the 37th or so 'other'.

    Modding the compiler took 90 seconds, and needed 4 extra lines of code. Setting up this test took 2-3 minutes.

    Simple, yes? Then you think that this could be done even more easily 50
    years ago.






    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Tim Rentsch@[email protected] to comp.lang.c on Tue Oct 13 16:45:04 2026
    From Newsgroup: comp.lang.c

    Michael S <[email protected]> writes:

    On Tue, 13 Oct 2026 07:40:30 -0700
    Tim Rentsch <[email protected]> wrote:

    Michael S <[email protected]> writes:

    On Mon, 12 Oct 2026 21:09:25 +0200
    David Brown <[email protected]> wrote:

    On 12/10/2026 21:02, Michael S wrote:

    On Sun, 11 Oct 2026 14:28:29 -0700
    Keith Thompson <[email protected]> wrote:

    bart <[email protected]> writes:
    [...]

    'break' to quit a loop early is part of the language, so why
    shouldn't someone make use it?

    Agreed. (There are coding styles that require loops to exit only
    at the bottom, but that's not what we're talking about.)

    It just its use can be interfered with when 'switch' is
    involved.

    Yes. Everyone here knows that, and knew it before you started
    talking about it.

    Michael S wrote above that "The cases where I want to break out
    of the loop from the switch in the body of the loop are very
    common." Tim Rentsch questioned the "very common" part of that,
    and asked for an example. You jumped in and asserted that an
    example isn't necessary, because you misunderstood what was
    being said.

    I didn't read the whole subthread, but from what I read it seems
    that the only reader that misunderstood my statement was David
    Brown. The rest, including bart, understood just fine.

    If I have misunderstood, I would love to be corrected. In a number
    of my posts I said I was not sure what you were talking about, and
    would need more explanation.

    I thought that my comment is hard to misunderstand, but you proved
    me wrong. So I'd try to elaborate:

    switch() nested within loop is very common in my practice and I
    suppose in practice of everybody else.

    In my practice, but obviously not in practice of Tim Rentsch, it
    is sufficiently common to want to transfer control from point within
    such nested switch to point immediately following the containing
    loop.

    Let me clarify my earlier comment. I'm not surprised that people
    routinely use switch() inside of loops. What did surprise me is the
    statement that wanting to break out of the loop from inside the
    switch() is "very common". Not happens occasionally; not happens
    commonly or even just sufficiently commonly; not happens routinely;
    but "very common". I am wondering now how common it actually is,
    for switch() in general and for switch() inside of a loop. Is it
    one in a hundred? One in ten? One in two? More than that?

    Of course, I never gathered exact statistics.
    My guts feeling is that among switches nested within loop it could be as
    high as one out of five. Not one out of five case labels, but one out of five switch statements.

    Gut feelings are fine. Thank you.

    I asked for an example because I am curious about what the proximate
    cause of such commonality might be. Is it a general style matter?
    Is it that you are used to certain patterns of local control flow?

    My own use cases are mostly related to processing of incoming network messages that are distinguished by opcode at the beginning of the
    message.

    Okay. Does this mean the loop exit indicates the end of the
    last packet so the last packet can be processed (and start
    another one presumably)? Or am I misunderstanding you?

    But not just that. Generally, I like small functions that return
    specialized enum as result code. When such functions used within
    loop, it often leads to pattern in question.

    I expect this pattern leads to using switch() more often. So that
    could account for part of it.

    Is it that some use cases are more common in the kinds of programs
    you deal with? It would be good to get some data here, even just
    ad hoc data.

    Sorry, right now I have no time for doing such analysis. It is not
    trivial exactly because 'C' has no such feature. So I don't know how
    to automate a search within codebases.

    An approximate measure is how often 'goto' is used inside a switch()
    body. That would be interesting to know in any case. Whether it
    would be easy to do that heuristically probably depends on what code
    base is being processed.

    In my own experience, wanting to escape multiple levels (including
    the case of provoking a loop exit from inside a switch()) doesn't
    happen often enough to merit considering a language change. But I
    would like to know more about the experiences of other people.

    I'm reminded of a quote from (if memory serves) Tony Hoare, about
    language design. Paraphrasing: A programming language should not
    reflect the union of all the features proposed by its designers;
    rather it should reflect the union of the designers' prejudices
    about what features should NOT be put into the language.

    In this particular case Ritchie did not have to innovate in order to
    create this feature. Quite opposite, as others (Keith ?) mentioned,
    he had to innovate in order to merge distinct break-loop and
    break-switch features of ancestor language into unified break.

    Sorry, it seems my comment led you astray. I was talking about
    something else. In any case Ritchie was operating under very
    different circumstances, including in particular more severe memory constraints. At the time adding another keyword to the language may
    have seemed like an extravagance.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@[email protected] to comp.lang.c on Tue Oct 13 18:27:36 2026
    From Newsgroup: comp.lang.c

    bart <[email protected]> writes:
    [...]
    My view is that using distinct keywords for loop-break and
    switch-break (accepting that the language wants the latter) would have
    had pretty much zero costs, but worthwhile benefits.

    I agree, and I don't think that's particularly controversial.

    The point on which we disagree is what can and should be done about
    it now.
    --
    Keith Thompson (The_Other_Keith) [email protected]
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@[email protected] to comp.lang.c on Tue Oct 13 18:34:12 2026
    From Newsgroup: comp.lang.c

    Michael S <[email protected]> writes:
    [...]
    In this particular case Ritchie did not have to innovate in order to
    create this feature. Quite opposite, as others (Keith ?) mentioned, he
    had to innovate in order to merge distinct break-loop and break-switch features of ancestor language into unified break.

    As Dan Cross pointed out, I didn't quite get this right. At the time
    C was invented, BCPL didn't have ENDCASE. BCPL continued to evolve independently after B and C were derived from it.

    This information is from Ritchie's HOPL (History or Programming
    Languages) paper, available at https://www.nokia.com/bell-labs/about/dennis-m-ritchie/chist.html

    Not every difference between the BCPL language documented in
    Richards's book [Richards 79] and B was deliberate; we started
    from an earlier version of BCPL [Richards 67]. For example,
    the endcase that escapes from a BCPL switchon statement was
    not present in the language when we learned it in the 1960s,
    and so the overloading of the break keyword to escape from the
    B and C switch statement owes to divergent evolution rather
    than conscious change.
    --
    Keith Thompson (The_Other_Keith) [email protected]
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@[email protected] to comp.lang.c on Tue Oct 13 18:44:05 2026
    From Newsgroup: comp.lang.c

    [email protected] (Dan Cross) writes:
    [...]
    Note this is the only place in that paper where Dennis Ritchie
    mentions `break`. Why was it overloaded for `switch`? He does
    not say, exactly, but he _does_ alude to space being a
    consideration for B, and some of the resulting syntactic quirks
    then escaping into C:
    [...]

    Pure speculation follows.

    I'm skeptical that space concerns were the reasons for not having a
    separate endcase keyword, though I suppose it's possible. (C had
    23 keywords as of 1974.) It seems more likely that Ritchie just
    didn't think of it.
    --
    Keith Thompson (The_Other_Keith) [email protected]
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From gazelle@[email protected] (Kenny McCormack) to comp.lang.c on Wed Oct 14 01:50:00 2026
    From Newsgroup: comp.lang.c

    In article <11amlq9$12efg$[email protected]>,
    Keith Thompson <[email protected]> wrote:
    bart <[email protected]> writes:
    [...]
    My view is that using distinct keywords for loop-break and
    switch-break (accepting that the language wants the latter) would have
    had pretty much zero costs, but worthwhile benefits.

    I agree, and I don't think that's particularly controversial.

    The point on which we disagree is what can and should be done about
    it now.

    The answer to that is: Invent new languages with C-like syntax, but better.
    You can't do anything about C, but you can do better as long as you call
    the result something else.

    Like C#. Like C++. Like Swift.
    --
    People seem to think that Youtube (and Facebook and Twitter and so on) is
    (are) some sort of resource created for the public good. Why they delude themselves into believing this is beyond my ability to comprehend.

    Usenet will always be here. Longer than people remember what port 80 was for. --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@[email protected] to comp.lang.c on Tue Oct 13 20:40:31 2026
    From Newsgroup: comp.lang.c

    bart <[email protected]> writes:
    On 13/10/2026 01:33, Keith Thompson wrote:
    [...]
    That's already happening. If you take a look at the N3886 working
    draft for C2y, it has named break statements.
    [...]
    There is already a solution for the problem you're complaining
    about.

    (It also solves the problem of breaking out of nested loops.)
    If you're unable to use this feature, you can use goto. That's not
    ideal, but with well chosen label names and no backward branching
    it's not too bad.

    I've got a better idea. I added an extra keyword to my C compiler
    called "breakloop". It's like 'break' but always works with the
    nearest enclosing loop, even from inside switch.

    Adding a keyword to your personal C compiler is easy. That's a tiny
    fraction of the effort needed to make a change to the language.

    Getting the WG14 committee to agree that your solution is a good idea,
    nailing down the exact wording that describes it, and waiting for all
    C compilers to implement it, is not.

    Sure, your "breakloop" could work, but it's blatantly nothing more
    than a workaround for one specific minor problem. Presumably if
    "breakloop" appears outside a switch statement it means exactly
    the same thing as "break". How are programmers to decide which
    one to use? Would you want to deprecate the use of "break" other
    than to break out of a switch statement?

    We have decades of precedent that "break" is how you break out of a
    loop. Your solution is to add a second way to do the same thing.

    Sorry, but it's ugly. I'd rather use goto. And there's already
    a more general solution planned for C2y.

    [...]

    Simple, yes? Then you think that this could be done even more easily
    50 years ago.

    It could have been done more easily 50 years ago than now. Using,
    say, "breaksw" for switch statements and "break" for loops would
    have been equally easy, and a better solution that what you propose.
    Allowing name for loops and switch statements is a more general
    solution to this and other problems, it's already been implemented,
    and it will almost certainly be standardized.

    I dislike the default fallthrough behavior of switch statements.
    If I were designing C today, I'd probably (a) *not* have default
    fallthrough, (b) add something like a "fallthrough" keyword for
    when you want it, and (c) have named loops. As of C2y, we'll have
    (c) but not (a) and (b) -- and that's good enough.
    --
    Keith Thompson (The_Other_Keith) [email protected]
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@[email protected] (Dan Cross) to comp.lang.c on Wed Oct 14 03:59:42 2026
    From Newsgroup: comp.lang.c

    In article <11amecs$10eab$[email protected]>, bart <[email protected]> wrote:
    On 13/10/2026 01:33, Keith Thompson wrote:
    bart <[email protected]> writes:
    [...]
    This is my first example expressed in C (note those first three args
    are passed by reference):

    while (pmtype = nextcmdparam(&paramno, &name, &value, "m") {
    switch (pmtype)
    case pm_option: ...; break;
    case pm_sourcefile:
    if (passlevel == run_pass || passlevel == runpcl_pass) {
    break;

    Except I can't use break like that. So I have to find a workaround.

    The code appears to be valid C that doesn't do what you want. I can't
    easily tell what you want it to do. I don't know which of the two break
    statements was intended to break out of the loop. A comment would have
    solved that.

    I'm going to guess that the first break is supposed to apply to the
    switch statement, and the second to the while loop.

    You want the language to be changed to make this kind of thing easier.

    That's already happening. If you take a look at the N3886 working
    draft for C2y, it has named break statements. In C2y (or in gcc
    if you use an extension), the above could be written as:

    WHILE:
    while (pmtype = nextcmdparam(&paramno, &name, &value, "m") {
    SWITCH:
    switch (pmtype)
    case pm_option: ...; break SWITCH;
    case pm_sourcefile:
    if (passlevel == run_pass || passlevel == runpcl_pass) {
    break WHILE;

    assuming it's the second "break' that's supposed to break out of
    the loop. (I'd probably use more meaninful names.)

    There is already a solution for the problem you're complaining about.
    (It also solves the problem of breaking out of nested loops.)

    If you're unable to use this feature, you can use goto. That's not
    ideal, but with well chosen label names and no backward branching
    it's not too bad.

    I've got a better idea. I added an extra keyword to my C compiler called >"breakloop". It's like 'break' but always works with the nearest
    enclosing loop, even from inside switch.

    So this example (a starts at 0):

    while (1) {
    switch (a++) {
    case 1: puts("one"); break;
    case 2: puts("two"); breakloop;
    case 3: puts("three"); break;
    default: puts("other");
    }

    if (a>40) break;
    }

    finishes after displaying 'two', instead of after the 37th or so 'other'.

    Modding the compiler took 90 seconds, and needed 4 extra lines of code. >Setting up this test took 2-3 minutes.

    Simple, yes? Then you think that this could be done even more easily 50 >years ago.

    Not really; for a general mechanism, if suffers from the obvious
    deficiency that it doesn't compose.

    For example, if the switch is inside of nested loops, and I
    want to break out of everything, or I have two embedded switches
    (which I have written when parsing firmware tables); I can think
    of a number of instances where you might want to have switch
    inside of nested loops and want to break out to function scope,
    such as advancing states a la a Thompson-style NFA, where one
    has a loop over the input text, a loop over the set of all
    states, and a switch matching state against the current input
    character, and you want to break out when you find a match.

    Many other languages solve this using a "labeled break" (Go,
    Rust, C#, Kotlin, Java, Ada, Pike, and now C), though some have
    used a "counted"/"multi-level" break (Ruby, Perl; I think PHP).

    You could have elegantly solved this problem by making `break`
    take an optional integer argument, which is the number of levels
    of structure to break out of. For a `switch` inside of a loop,
    `break 2;` would exit both the case and the enclosing loop; for
    a nested switch, `break 2;` would break out of both. Workable,
    but in some respects the labeled form is better because it is
    resilient to code shuffling around and changing nesting levels
    and so forth.

    An obvious next extension would be augmenting `continue`
    similarly.

    But as Keith pointed out, W14 is now entertaining proposals to
    add labeled `break` to the language. I haven't looked myself,
    but if that is usable in a `switch` context, then it would solve
    the problem for good.

    This illustrates one reason why changing a language can be hard:
    your idea sounds good at first blush, but it has its own
    deficiencies.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@[email protected] to comp.lang.c on Tue Oct 13 21:35:14 2026
    From Newsgroup: comp.lang.c

    [email protected] (Dan Cross) writes:
    [...]
    Many other languages solve this using a "labeled break" (Go,
    Rust, C#, Kotlin, Java, Ada, Pike, and now C), though some have
    used a "counted"/"multi-level" break (Ruby, Perl; I think PHP).

    The only languages I know of that have a "counted break" (where
    "break 2" breaks out of two levels of loops) are the Bourne shell
    and shells derived from it, and PHP (you're right about that).

    Perl has named break (spelled "last" or "last NAME") and continue
    (spelled "next" or "next NAME). It does not have counted versions.

    Ruby allows an argument on "break", but it's not the number of levels.
    It specifies the value of the expression that it breaks out of. (A
    loop is an expression that can yield a value.)

    The latest draft of the C++ standard does not include labeled break
    and continue statements. I don't know whether it's been proposed.

    You could have elegantly solved this problem by making `break`
    take an optional integer argument, which is the number of levels
    of structure to break out of.

    I don't consider that elegant, for reasons I've already ranted about
    here.

    [...]

    But as Keith pointed out, W14 is now entertaining proposals to
    add labeled `break` to the language. I haven't looked myself,
    but if that is usable in a `switch` context, then it would solve
    the problem for good.

    Yes, labeled "break" in C2y applies to both loops and switch statements. There's also a labeled "continue" that applies only to loops.
    The labels are optional, so existing code isn't broken.

    The latest C2y draft is <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3886.pdf>
    (3.3 MB, 793 pages).

    This illustrates one reason why changing a language can be hard:
    your idea sounds good at first blush, but it has its own
    deficiencies.
    --
    Keith Thompson (The_Other_Keith) [email protected]
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Kaz Kylheku@[email protected] to comp.lang.c on Wed Oct 14 05:17:12 2026
    From Newsgroup: comp.lang.c

    On 2026-10-13, Michael S <[email protected]> wrote:
    Of course, I never gathered exact statistics.
    My guts feeling is that among switches nested within loop it could be as
    high as one out of five. Not one out of five case labels, but one out of
    five switch statements.

    Switches inside a loop are natural whenever a state machine is being
    simulated which has acceptance/failulre states which indicate that the simulation should end.

    Switches inside a loop are also natural whenever a stream of
    integer-tagged cases is being handled where a terminating sentinel is
    also labeled.

    There are at least two workarounds for writing this which avoid
    duplicated testing or loop termination flags, gotos or such.

    One is to make the loop the last statement of a function and use
    "return" in the loop-terminating cases.

    The other is to put a "break" at the bottom of the loop and
    terminate all the loop-continuing cases with "continue",
    the terminating cases with "break":

    for (;;) {
    int ch = getc(in);
    switch (ch) {
    case '\n':
    lines++;
    /* fallthrough */
    default:
    continue;
    case EOF:
    break;
    }
    break;
    }
    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @[email protected]
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@[email protected] (Dan Cross) to comp.lang.c on Wed Oct 14 10:53:21 2026
    From Newsgroup: comp.lang.c

    In article <11am9r9$4o6m$[email protected]>,
    Janis Papanagnou <[email protected]> wrote:
    On 2026-10-13 22:52, Dan Cross wrote:

    Were you referring to me, Janis? Or to bart?

    You can identify the association of the answers by its attribution
    indent level. - Most was attributed to bart's text that was quoted.

    Sure. I was just surprised that the reply to my post was the
    vehicle to reply to bart. Anyway, no worries!

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@[email protected] (Dan Cross) to comp.lang.c on Wed Oct 14 10:58:45 2026
    From Newsgroup: comp.lang.c

    In article <11amn48$7ell$[email protected]>,
    Kenny McCormack <[email protected]> wrote:
    In article <11amlq9$12efg$[email protected]>,
    Keith Thompson <[email protected]> wrote:
    bart <[email protected]> writes:
    [...]
    My view is that using distinct keywords for loop-break and
    switch-break (accepting that the language wants the latter) would have
    had pretty much zero costs, but worthwhile benefits.

    I agree, and I don't think that's particularly controversial.

    The point on which we disagree is what can and should be done about
    it now.

    The answer to that is: Invent new languages with C-like syntax, but better. >You can't do anything about C, but you can do better as long as you call
    the result something else.

    Like C#. Like C++. Like Swift.

    I mean...we've got a ton of those now. Go, Rust, Zig, Switch,
    and on and on. We don't really need to invent new languages.
    OCaml, Haskell, Julia, ad infinitum.

    In my view, the bigger impediments to moving off of C as the
    dominant systems programming language are two fold:
    1. providing a clean path from C to the new language(s), and
    2. overcoming the enormous inertia of decades of defaulting to C
    for systems programs.

    I love C, but I'm not in love with C anymore, and if I am
    starting a new project these days, it's not the first thing I
    reach for anymore.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Wed Oct 14 12:17:01 2026
    From Newsgroup: comp.lang.c

    On 14/10/2026 04:59, Dan Cross wrote:
    In article <11amecs$10eab$[email protected]>, bart <[email protected]> wrote:

    I've got a better idea. I added an extra keyword to my C compiler called
    "breakloop". It's like 'break' but always works with the nearest
    enclosing loop, even from inside switch.

    So this example (a starts at 0):

    while (1) {
    switch (a++) {
    case 1: puts("one"); break;
    case 2: puts("two"); breakloop;
    case 3: puts("three"); break;
    default: puts("other");
    }

    if (a>40) break;
    }

    finishes after displaying 'two', instead of after the 37th or so 'other'.

    Modding the compiler took 90 seconds, and needed 4 extra lines of code.
    Setting up this test took 2-3 minutes.

    (I've now simplified it to adding one extra line and tweaking another!

    I'd even suggest that using distinct keywords in the original C compiler
    would have made it a tiny bit simpler.)


    Simple, yes? Then you think that this could be done even more easily 50
    years ago.

    Not really; for a general mechanism, if suffers from the obvious
    deficiency that it doesn't compose.

    For example, if the switch is inside of nested loops, and I
    want to break out of everything,

    This isn't the problem being discussed. IME breaking of nested loops is uncommon, but breaking out of a loop from inside switch /is/ common.

    It's using the same 'break' keyword that makes that awkward in C. And my experiment solves that easily.


    or I have two embedded switches

    That's not a problem; 'breakloop' will completely ignore any switch statements, in the same way that 'continue' does.

    Unless you've invented a new requirement where you want 'break' within a switch (itself solving an artificial problem) to jump straight to the
    end of an outer switch.

    (which I have written when parsing firmware tables); I can think
    of a number of instances where you might want to have switch
    inside of nested loops and want to break out to function scope,
    such as advancing states a la a Thompson-style NFA, where one
    has a loop over the input text, a loop over the set of all
    states, and a switch matching state against the current input
    character, and you want to break out when you find a match.

    'Jumping to function scope' is poorly defined. Do you mean cutting
    across not only all loops, but any containing nested 'if' and 'switch' statements?

    So that would be a separate feature from loop-break? Would it still
    involve loops at all, or could it be used from within any statement?

    That sounds too general and wide-reaching; I think 'goto' is a much
    better fit for that, if 'return' or 'defer' wouldn't work.

    Many other languages solve this using a "labeled break" (Go,
    Rust, C#, Kotlin, Java, Ada, Pike, and now C), though some have
    used a "counted"/"multi-level" break (Ruby, Perl; I think PHP).

    You could have elegantly solved this problem by making `break`
    take an optional integer argument, which is the number of levels
    of structure to break out of.

    I could have done that in C but it would have taken more than 5 minutes,
    and this was anyway a proof of concept.

    I've already used that approach for some decades in my other languages,
    but as I showed in the tables I posted, it is not common, and where
    used, it was always to break out of all loops.

    Anyway, I normally use 'all' instead of a specific number to quit all
    loops. A number works too but I dislike it.


    For a `switch` inside of a loop,
    `break 2;` would exit both the case and the enclosing loop; for
    a nested switch, `break 2;` would break out of both. Workable,
    but in some respects the labeled form is better because it is
    resilient to code shuffling around and changing nesting levels
    and so forth.

    No, it just has a different set of problems. For example, you label the
    outer loop and exit to that. Now you add an extra outer loop layer: does
    that label go inside this new loop or outside?

    That depends on the intended logic, which you don't know.

    Maybe the original set of loop performed some task T, and the new loop
    wants to repeat T, in which case it must stay inside.

    Or maybe it is really has to quit ALL loops including any future outer
    ones. Neither labeling or numbering solves this.

    Labeled loops may also have a new problem with scoping: is the loop name
    local to this nest of loops, or could an outer loop name especially
    clash with other loop elsewhere?


    An obvious next extension would be augmenting `continue`
    similarly.

    In my other languages, I use 'exit' for break, and 'nextloop' for
    continue, and 'redoloop' to repeat iteration. (The latter will have
    different behaviour inside a for-loop with formal loop variables.)

    I've just done a survey in my major apps and haven't found an instance
    where those latter two needed to cross two or more loops.

    Although I am sure C programmers would put 'continue x' to good use if
    it was available!


    But as Keith pointed out, W14 is now entertaining proposals to
    add labeled `break` to the language. I haven't looked myself,
    but if that is usable in a `switch` context, then it would solve
    the problem for good.


    OK. Although in that form, it really is little different from 'goto'. I believe the main difference is that the label goes at the beginning of
    the loop rather than the end!

    And maybe those scoping rules will be different: goto labels have function-wide scope.

    This illustrates one reason why changing a language can be hard:
    your idea sounds good at first blush, but it has its own
    deficiencies.
    I appreciate your concern. I've only been doing this (devising and implementing systems languages) for 45 years!
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@[email protected] (Dan Cross) to comp.lang.c on Wed Oct 14 11:27:08 2026
    From Newsgroup: comp.lang.c

    In article <11an0q3$14pou$[email protected]>,
    Keith Thompson <[email protected]> wrote: >[email protected] (Dan Cross) writes:
    [...]
    Many other languages solve this using a "labeled break" (Go,
    Rust, C#, Kotlin, Java, Ada, Pike, and now C), though some have
    used a "counted"/"multi-level" break (Ruby, Perl; I think PHP).

    The only languages I know of that have a "counted break" (where
    "break 2" breaks out of two levels of loops) are the Bourne shell
    and shells derived from it, and PHP (you're right about that).

    Perl has named break (spelled "last" or "last NAME") and continue
    (spelled "next" or "next NAME). It does not have counted versions.

    Ruby allows an argument on "break", but it's not the number of levels.
    It specifies the value of the expression that it breaks out of. (A
    loop is an expression that can yield a value.)

    Ah, you're right and I was simply wrong about Perl and Ruby. I
    must have hallucinated those.

    Regarding expression oriented languages where constructs like
    loops can return values, it's somewhat ironic that BCPL could do
    something like that using its, `valof`/`resultis` mechanism; I
    have often wanted something like that in C; it would obviate the
    ternary operator.

    The latest draft of the C++ standard does not include labeled break
    and continue statements. I don't know whether it's been proposed.

    That's unfortunate. I wonder if that's merely an oversight, or
    a conscious decision; I'll have to look it up later.

    You could have elegantly solved this problem by making `break`
    take an optional integer argument, which is the number of levels
    of structure to break out of.

    I don't consider that elegant, for reasons I've already ranted about
    here.

    Fair. I do believe that the labeled variant is better for a
    host of reasons, though I don't love the syntax, but that is
    merely a subjective aesthetic judgement on my part.

    [...]

    But as Keith pointed out, W14 is now entertaining proposals to
    add labeled `break` to the language. I haven't looked myself,
    but if that is usable in a `switch` context, then it would solve
    the problem for good.

    Yes, labeled "break" in C2y applies to both loops and switch statements. >There's also a labeled "continue" that applies only to loops.
    The labels are optional, so existing code isn't broken.

    The latest C2y draft is ><https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3886.pdf>
    (3.3 MB, 793 pages).

    (Thanks; I've been meaning to download a copy of the latest
    draft anyway.)

    It seems that the matter is settled conclusively, and this
    entire thread is lots of heat and light generated for no reason.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@[email protected] (Dan Cross) to comp.lang.c on Wed Oct 14 12:38:22 2026
    From Newsgroup: comp.lang.c

    In article <11anobe$1dt0e$[email protected]>, bart <[email protected]> wrote:
    On 14/10/2026 04:59, Dan Cross wrote:
    In article <11amecs$10eab$[email protected]>, bart <[email protected]> wrote:
    I've got a better idea. I added an extra keyword to my C compiler called >>> "breakloop". It's like 'break' but always works with the nearest
    enclosing loop, even from inside switch.

    So this example (a starts at 0):

    while (1) {
    switch (a++) {
    case 1: puts("one"); break;
    case 2: puts("two"); breakloop;
    case 3: puts("three"); break;
    default: puts("other");
    }

    if (a>40) break;
    }

    finishes after displaying 'two', instead of after the 37th or so 'other'. >>>
    Modding the compiler took 90 seconds, and needed 4 extra lines of code.
    Setting up this test took 2-3 minutes.

    (I've now simplified it to adding one extra line and tweaking another!

    I'd even suggest that using distinct keywords in the original C compiler >would have made it a tiny bit simpler.)

    Unlikely. I'm trying to chase down the citation, but it was
    known that getting B to fit on the PDP-7 was a challenge. From
    the C history paper,

    |After the TMG version of B was working, Thompson rewrote B in
    |itself (a bootstrapping step). During development, he
    |continually struggled against memory limitations: each language
    |addition inflated the compiler so it could barely fit, but each
    |rewrite taking advantage of the feature reduced its size. For
    |example, B introduced generalized assignment operators, using
    |`x=+y` to add `y` to `x`. The notation came from Algol 68
    |[Wijngaarden 75] via McIlroy, who had incorporated it into his
    |version of TMG. (In B and early C, the operator was spelled
    |`=+` instead of `+=`; this mistake, repaired in 1976, wa
    | induced by a seductively easy way of handling the first form
    |in B's lexical analyzer.) (https://www.nokia.com/bell-labs/about/dennis-m-ritchie/chist.html)
    [Context: "TMG" was a compiler-compiler, similar to yacc]

    Early C was not much better. Compiler sources for some of the
    earliest Unix C compilers are available, and pretty interesting
    reads: one can see that great pains were taken so that the
    compiler actually fits onto the machine. By the time they were
    on a PDP-11/45 class machine (with split I- and D-space) things
    were somewhat better, but by then the basic design of the
    language was set and adding an extra keyword just for
    terminating cases in a `switch` was likely seen as unnecessary.

    Simple, yes? Then you think that this could be done even more easily 50
    years ago.

    Not really; for a general mechanism, if suffers from the obvious
    deficiency that it doesn't compose.

    For example, if the switch is inside of nested loops, and I
    want to break out of everything,

    This isn't the problem being discussed. IME breaking of nested loops is >uncommon, but breaking out of a loop from inside switch /is/ common.

    The irony here, of course, is that you are claiming that C is
    deficient because it doesn't solve what you see as a problem,
    but trying to force the problem space specifically so that it
    fits the solution your proposed, so that you can avoid
    confronting that proposal's deficiencies.

    The problem space is actually much wider than what you have
    narrowly defined it to be. *You* don't see that as interesting,
    so you simply ignore it.

    In this sense, your proposal is strictly a regression: it adds
    complexity to the language by introducing a new keyword, but it
    only solves one tiny problem, but nothing beyond that.

    Yes, I am aware that you will tell me that it is justified
    because that problem is actually the one worth solving, and the
    others are not; you needn't bother. Simply put, I disagree that
    that one problem is sufficiently important to warrant its own
    solution, particularly when something more general is already
    known and available in the language (labeled break/continue).

    It's using the same 'break' keyword that makes that awkward in C. And my >experiment solves that easily.

    ...except for all the other cases where it is still awkward and
    solves nothing.

    or I have two embedded switches

    That's not a problem; 'breakloop' will completely ignore any switch >statements, in the same way that 'continue' does.

    Yes, but it does nothing to break out of the outer switch, if
    that's what I want; the inner switch might be followed by more
    statements in the case it is nested in.

    Unless you've invented a new requirement where you want 'break' within a >switch (itself solving an artificial problem) to jump straight to the
    end of an outer switch.

    Yes, that's exactly what I'm saying. Again, you've identified
    one narrow problem, proposed a solution for that problem, and
    decided any identified issues with that solution don't apply
    because they don't affect the narrowly defined problem that you
    have decided is important.

    Past behavior suggests that you imagine that anyone pointing out
    a reason why your solution may not be everything you think it is
    is somehow unfairly changing the rules of the game in order to
    give you a hard time. But consider: perhaps they're just
    pointing out a reason why your solution isn't optimal.

    I think this is the central reason people don't take your
    criticism of C particularly seriously. There is space for
    discussing how C _could_ be different, but if you are not
    willing to engage in actually understanding the problems, and
    actually, I don't know, having a discussion about your proposed
    solutions and recognizing when they fall short, then you're not
    being serious.

    (which I have written when parsing firmware tables); I can think
    of a number of instances where you might want to have switch
    inside of nested loops and want to break out to function scope,
    such as advancing states a la a Thompson-style NFA, where one
    has a loop over the input text, a loop over the set of all
    states, and a switch matching state against the current input
    character, and you want to break out when you find a match.

    'Jumping to function scope' is poorly defined. Do you mean cutting
    across not only all loops, but any containing nested 'if' and 'switch' >statements?

    What I mean is this:

    void
    foo(void)
    {
    for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; i++) {
    switch (something) {
    case ...:
    // I want to break out
    // of the switch and
    // both loops here.
    goto label;
    }
    }
    }
    label:
    }

    So that would be a separate feature from loop-break? Would it still
    involve loops at all, or could it be used from within any statement?

    That sounds too general and wide-reaching; I think 'goto' is a much
    better fit for that, if 'return' or 'defer' wouldn't work.

    Why? The labeled break mechanism that looks like it's coming in
    C2Y neatly solves this and your original problem; it's a
    consistent, general mechanism. It also handles loops inside of
    switches, and other cases your proposal doesn't handle.

    Many other languages solve this using a "labeled break" (Go,
    Rust, C#, Kotlin, Java, Ada, Pike, and now C), though some have
    used a "counted"/"multi-level" break (Ruby, Perl; I think PHP).

    You could have elegantly solved this problem by making `break`
    take an optional integer argument, which is the number of levels
    of structure to break out of.

    I could have done that in C but it would have taken more than 5 minutes,
    and this was anyway a proof of concept.

    Yup. And it took less than that to point out problems.

    I've already used that approach for some decades in my other languages,
    but as I showed in the tables I posted, it is not common, and where
    used, it was always to break out of all loops.

    Anyway, I normally use 'all' instead of a specific number to quit all
    loops. A number works too but I dislike it.

    That sounds overly specific.

    For a `switch` inside of a loop,
    `break 2;` would exit both the case and the enclosing loop; for
    a nested switch, `break 2;` would break out of both. Workable,
    but in some respects the labeled form is better because it is
    resilient to code shuffling around and changing nesting levels
    and so forth.

    No, it just has a different set of problems. For example, you label the >outer loop and exit to that. Now you add an extra outer loop layer: does >that label go inside this new loop or outside?

    This is actually the argument against the counted multi-level
    break: if I add or remove a level of nesting, I have to find and
    adjust all of the counts. The labeled break mechanism ties the
    `break` or `continue` to another syntactic element (a label), so
    if I add or remove a nesting level, I'm still breaking to where
    I had intended to before.

    That said, applying the argument to the labeled case is silly.
    Software engineering and good programming practice still matter.
    If you are changing the nested looping structure of your
    program, then you should know where you want to break to;
    presumably your program's behavior depends on it.

    I'd say the stronger argument for the labeled control structure
    is actually nested switch statements, where I may change a
    series of `if`s to a `switch` with a `case` that contains a
    nested `switch`, or I may change a `switch` to an `if`; if the
    intent is to break out of an enclosing loop, labeled breaks are
    resilient to that, but counted breaks are not.

    That depends on the intended logic, which you don't know.

    Yes.

    Maybe the original set of loop performed some task T, and the new loop
    wants to repeat T, in which case it must stay inside.

    Yes.

    Or maybe it is really has to quit ALL loops including any future outer
    ones. Neither labeling or numbering solves this.

    No. If I want to break out of *all* loops, I just make sure
    that the outermost loop is labeled thusly.

    Labeled loops may also have a new problem with scoping: is the loop name >local to this nest of loops, or could an outer loop name especially
    clash with other loop elsewhere?

    Since labels are, you know, labels, they follow the semantics of
    ... labels.

    An obvious next extension would be augmenting `continue`
    similarly.

    In my other languages, I use 'exit' for break, and 'nextloop' for
    continue, and 'redoloop' to repeat iteration. (The latter will have >different behaviour inside a for-loop with formal loop variables.)

    I've just done a survey in my major apps and haven't found an instance
    where those latter two needed to cross two or more loops.

    Anecdotal evidence, I'm afraid.

    Although I am sure C programmers would put 'continue x' to good use if
    it was available!

    Yes.

    But as Keith pointed out, W14 is now entertaining proposals to
    add labeled `break` to the language. I haven't looked myself,
    but if that is usable in a `switch` context, then it would solve
    the problem for good.

    OK. Although in that form, it really is little different from 'goto'. I >believe the main difference is that the label goes at the beginning of
    the loop rather than the end!

    The problem there is that `break` and `continue` would require
    different labels: `continue loop;` conceptually jumps to the
    _end_ of the loop body, and resumes on the next iteration, while
    `break loop;` jumps to the next statement immediately following
    the loop body. With the named-label mechanism, the same "name"
    can be used for both.

    And maybe those scoping rules will be different: goto labels have >function-wide scope.

    It's easy enough to look it up in the draft document; Keith
    posted a link.

    This illustrates one reason why changing a language can be hard:
    your idea sounds good at first blush, but it has its own
    deficiencies.

    I appreciate your concern. I've only been doing this (devising and >implementing systems languages) for 45 years!

    That really doesn't mean anything. Just doing something for a
    long time doesn't mean you're good at it: I have been shooting
    baskets for 45 years, but I will never be a point guard in the
    NBA.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Wed Oct 14 13:46:33 2026
    From Newsgroup: comp.lang.c

    On 14/10/2026 06:17, Kaz Kylheku wrote:
    On 2026-10-13, Michael S <[email protected]> wrote:
    Of course, I never gathered exact statistics.
    My guts feeling is that among switches nested within loop it could be as
    high as one out of five. Not one out of five case labels, but one out of
    five switch statements.

    Switches inside a loop are natural whenever a state machine is being simulated which has acceptance/failulre states which indicate that the simulation should end.

    Switches inside a loop are also natural whenever a stream of
    integer-tagged cases is being handled where a terminating sentinel is
    also labeled.

    There are at least two workarounds for writing this which avoid
    duplicated testing or loop termination flags, gotos or such.

    One is to make the loop the last statement of a function and use
    "return" in the loop-terminating cases.

    The other is to put a "break" at the bottom of the loop and
    terminate all the loop-continuing cases with "continue",
    the terminating cases with "break":

    for (;;) {
    int ch = getc(in);
    switch (ch) {
    case '\n':
    lines++;
    /* fallthrough */
    default:
    continue;
    case EOF:
    break;
    }
    break;
    }


    Well, it's a novel workaround, but it is still a workaround if the logic
    could have been more naturally expressed like this:

    for (;;) {
    switch (ch = getch()) { // I assume ch needed for other cases
    case '\n':
    lines++;
    break;
    case EOF:
    BREAK;
    }
    }

    BREAK represents loop exit. The point is to avoid having to restructure
    your code just to get around a silly shortcoming. In practice, using
    'goto' is the simplest workaround.


    (This a pattern that is common enough for me to have a special syntax
    for in my projects. Then it is expressed as:)

    doswitch ch := getch(in)
    when '\n' then
    ++lines
    when EOF then
    exit
    end


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From scott@[email protected] (Scott Lurndal) to comp.lang.c on Wed Oct 14 14:35:55 2026
    From Newsgroup: comp.lang.c

    bart <[email protected]> writes:
    On 13/10/2026 01:33, Keith Thompson wrote:
    bart <[email protected]> writes:
    [...]

    I've got a better idea. I added an extra keyword to my C compiler called >"breakloop". It's like 'break' but always works with the nearest
    enclosing loop, even from inside switch.

    It's hardly a new idea. The 1967 BPL compiler at burroughs
    supported 'EXITLOOP', 'EXITCOND', 'EXITCASE' and 'EXITBLOCK';
    each with the expected semantics for the name.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Wed Oct 14 16:49:35 2026
    From Newsgroup: comp.lang.c

    On 14/10/2026 13:38, Dan Cross wrote:
    In article <11anobe$1dt0e$[email protected]>, bart <[email protected]> wrote:

    I'd even suggest that using distinct keywords in the original C compiler
    would have made it a tiny bit simpler.)

    Unlikely. I'm trying to chase down the citation, but it was
    known that getting B to fit on the PDP-7 was a challenge. From
    the C history paper,

    Perhaps Switch should have been left out then if it was that tight.

    Sharing a keyword is just crass. Or maybe they should have considered
    not needing 'break' for switch.

    The irony here, of course, is that you are claiming that C is
    deficient because it doesn't solve what you see as a problem,
    but trying to force the problem space specifically so that it

    No, /you/ are trying to discredit a simple solution by widening the
    goalposts.

    The main problem being discussed, and the one my test fixed, is that of 'break' being used for two purposes and therefore resulting in clashes
    when Switches and Loops are mixed.

    That could easily have been fixed by DMR choosing to use distinct
    keywords. Do you agree so far?

    That of breaking out of nested loops is a different problem that would
    need a different solution, and nothing to do with the clash with switch.

    It is also one that seems to be about 100 times less common IME.


    ...except for all the other cases where it is still awkward and
    solves nothing.

    IT WAS ONLY SUPPOSED TO SOLVE THIS PROBLEM! Namely the issues that
    ensued from DMR overloading 'break'. NOTHING ELSE.

    In fact the confusion between switch-break and loop-break will still be
    there even if labels are added.
    Unless you've invented a new requirement where you want 'break' within a
    switch (itself solving an artificial problem) to jump straight to the
    end of an outer switch.

    Yes, that's exactly what I'm saying. Again, you've identified
    one narrow problem,

    It's not that narrow a problem, unless you want to call loops themselves
    a narrow feature.

    It is one that many languages solve for LOOPs by using break or
    equivalent. But they tend not to broaden it either to include breaks out
    of arbitrary kinds of blocks.

    I think this is the central reason people don't take your
    criticism of C particularly seriously.

    I'm sorry but here I don't take yours seriously either. (Have you ever implemented any of this stuff, or even used such features that you propose?)


    'Jumping to function scope' is poorly defined. Do you mean cutting
    across not only all loops, but any containing nested 'if' and 'switch'
    statements?

    What I mean is this:

    void
    foo(void)
    {
    for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; i++) {
    switch (something) {
    case ...:
    // I want to break out
    // of the switch and
    // both loops here.
    goto label;
    }
    }
    }
    label:
    }

    This example just breaks out of both loops. That the outer one is at
    function scope is incidental.

    If the outer loop was contained within an IF statement, could you jump
    to outside that statement using your proposed feature? If not then that
    is not function scope.

    I could have done that in C but it would have taken more than 5
    minutes,>> and this was anyway a proof of concept.

    Yup. And it took less than that to point out problems.

    But it solved the problem I wanted to solve! It would solve the problem Michael S reported! That is, using distinct keywords for two different
    things.

    I've already used that approach for some decades in my other languages,
    but as I showed in the tables I posted, it is not common, and where
    used, it was always to break out of all loops.

    Anyway, I normally use 'all' instead of a specific number to quit all
    loops. A number works too but I dislike it.

    That sounds overly specific.

    So is breaking out of an inner loop with 'break;'! But it works well as
    it's by far the most common requirement. The next most common IME is to
    quit all loops (like you do in your example).

    In fact, if there are only two nested loops, the inner and outer cover
    all the possibilities.

    This is actually the argument against the counted multi-level
    break: if I add or remove a level of nesting, I have to find and
    adjust all of the counts. The labeled break mechanism ties the
    `break` or `continue` to another syntactic element (a label), so

    No, it's just another set of problems as I said.

    You can add new inner loops, delete inner loops, add outer ones, and
    each time you will need to consider whether the labels need to be moved,
    or extra ones added.

    Here's another solution I favour (not implemented), but it only works
    for FOR loops:

    for i in a..b
    for j in c..d
    ... break i

    It's a little like using a label, but here that 'label' is the loop
    index. (This won't work in C as there are no formal loop indices.)

    if I add or remove a nesting level, I'm still breaking to where
    I had intended to before.

    Yes, but that might now be the wrong loop.

    That said, applying the argument to the labeled case is silly.
    Software engineering and good programming practice still matter.
    If you are changing the nested looping structure of your
    program, then you should know where you want to break to;
    presumably your program's behavior depends on it.

    Agreed; see below.

    I'd say the stronger argument for the labeled control structure
    is actually nested switch statements, where I may change a
    series of `if`s to a `switch` with a `case` that contains a
    nested `switch`, or I may change a `switch` to an `if`; if the
    intent is to break out of an enclosing loop, labeled breaks are
    resilient to that, but counted breaks are not.

    You're assuming that the count in indexed breaks includes switch
    statements. It shouldn't; that would be preposterous, and it all still
    comes down to the shared 'break' keyword.

    How about fixing that first, or even admitting it was wrong, before

    Maybe the original set of loop performed some task T, and the new
    loop>> wants to repeat T, in which case it must stay inside.

    Yes.

    Or maybe it is really has to quit ALL loops including any future outer
    ones. Neither labeling or numbering solves this.

    No. If I want to break out of *all* loops, I just make sure
    that the outermost loop is labeled thusly.

    But in my first example, that is not what you want! It all depends.

    I don't like using multi-level loop exit, it's an untidy feature even
    though I implement it. And I don't like using labeled solutions, as they
    just turn them into thinly disguised gotos.

    Labeled loops may also have a new problem with scoping: is the loop name
    local to this nest of loops, or could an outer loop name especially
    clash with other loop elsewhere?

    Since labels are, you know, labels, they follow the semantics of
    ... labels.
    Careful here: do you really mean that loop-labels will be in the same name-space as ordinary labels? That means:

    * Getting clashes when a labeled loop is copied elsewhere within the
    function

    * Being able to do an ordinary 'goto' to a loop-label ...

    * ... which will also be confusing when loop labels are placed at the
    beginning of a loop rather than the end:

    L1:
    while () {
    goto L1: This jumps to L1
    goto L2; This jumps to L2
    continue L1; This jumps to L2
    break L1; This jumps to L3
    L2:
    }
    L3:

    See there's a bit more to this language-design lark!


    I've just done a survey in my major apps and haven't found an instance
    where those latter two needed to cross two or more loops.

    Anecdotal evidence, I'm afraid.

    You're welcome to post your own surveys. Although unless the languages
    used in your survey support such features, you may find that hard.

    It's easy enough to look it up in the draft document; Keith
    posted a link.

    Is that that 793-page document? Perhaps you can summarise how it works!


    This illustrates one reason why changing a language can be hard:
    your idea sounds good at first blush, but it has its own
    deficiencies.

    I appreciate your concern. I've only been doing this (devising and
    implementing systems languages) for 45 years!

    That really doesn't mean anything. Just doing something for a
    long time doesn't mean you're good at it: I have been shooting
    baskets for 45 years, but I will never be a point guard in the
    NBA.
    And yet I've solved all the problems in this thread and many others.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@[email protected] to comp.lang.c on Wed Oct 14 17:54:44 2026
    From Newsgroup: comp.lang.c

    On 2026-10-14 12:53, Dan Cross wrote:
    In article <11am9r9$4o6m$[email protected]>,
    Janis Papanagnou <[email protected]> wrote:
    On 2026-10-13 22:52, Dan Cross wrote:

    Were you referring to me, Janis? Or to bart?

    You can identify the association of the answers by its attribution
    indent level. - Most was attributed to bart's text that was quoted.

    Sure. I was just surprised that the reply to my post was the
    vehicle to reply to bart. Anyway, no worries!

    I'm sorry for that. I stopped reading bart's posts for various
    reasons rooted in his personal, um.., communication style, and
    the mass of his posts of, um.., peculiar content. I don't want
    to contribute to that flood any more. But occasionally I see
    that other posters take that task (or burden?) to reply to him,
    and reading their posts I then see also what bart wrote, and
    occasionally still comment on what I then see. (Going to try
    reducing that as well; as it's rarely worth the hassle in this
    specific case.)

    Janis

    PS: I've just read another long (300 lines) post you made in
    reply to bart. Let me express my admiration for your patience
    and countenance (that I'm clearly lacking in this case), and
    the very clear form and conclusively explained content.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Wed Oct 14 18:51:28 2026
    From Newsgroup: comp.lang.c

    On 14/10/2026 13:38, Dan Cross wrote:
    In article <11anobe$1dt0e$[email protected]>, bart <[email protected]> wrote:

    Yes, I am aware that you will tell me that it is justified
    because that problem is actually the one worth solving, and the
    others are not; you needn't bother. Simply put, I disagree that
    that one problem is sufficiently important to warrant its own
    solution, particularly when something more general is already
    known and available in the language (labeled break/continue).

    I missed this bit.

    Is labeled break now available in C?

    If so, how would it be used here:


    while (1) {
    switch (x) {
    case y:
    Break;

    where that Break is meant to quit the loop.

    Remember that if DMR hadn't made that screw-up in 1972 it would simply
    have been as it is above with his choice of keyword in place of Break.

    But I would be interested in trying out the new feature.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Peyton@[email protected] to comp.lang.c on Wed Oct 14 11:04:04 2026
    From Newsgroup: comp.lang.c

    bart <[email protected]> writes:

    On 14/10/2026 13:38, Dan Cross wrote:
    In article <11anobe$1dt0e$[email protected]>, bart <[email protected]> wrote:

    Yes, I am aware that you will tell me that it is justified
    because that problem is actually the one worth solving, and the
    others are not; you needn't bother. Simply put, I disagree that
    that one problem is sufficiently important to warrant its own
    solution, particularly when something more general is already
    known and available in the language (labeled break/continue).

    I missed this bit.

    Is labeled break now available in C?

    If so, how would it be used here:


    while (1) {
    switch (x) {
    case y:
    Break;

    where that Break is meant to quit the loop.

    Remember that if DMR hadn't made that screw-up in 1972 it would simply
    have been as it is above with his choice of keyword in place of Break.

    But I would be interested in trying out the new feature.


    No it's definetely not supported yet. I am very much in support of it
    though. Not sure when or if. In the meantime I guess you can use the
    forbidden goto like so:

    while(1) {
    switch(x) {
    case 1:
    doThing();
    break;
    case 2:
    goto exitLoop;
    default:
    break;
    }
    }

    exitLoop;
    --
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@[email protected] (Dan Cross) to comp.lang.c on Wed Oct 14 19:30:28 2026
    From Newsgroup: comp.lang.c

    In article <11ao8af$1k8p3$[email protected]>, bart <[email protected]> wrote:
    On 14/10/2026 13:38, Dan Cross wrote:
    In article <11anobe$1dt0e$[email protected]>, bart <[email protected]> wrote:
    I'd even suggest that using distinct keywords in the original C compiler >>> would have made it a tiny bit simpler.)

    Unlikely. I'm trying to chase down the citation, but it was
    known that getting B to fit on the PDP-7 was a challenge. From
    the C history paper,

    Perhaps Switch should have been left out then if it was that tight.

    Why? It's genuinely useful.

    Sharing a keyword is just crass.

    Don't you share `end`?

    Or maybe they should have considered
    not needing 'break' for switch.

    Maybe? And yet here we are, 50+ years later.

    The irony here, of course, is that you are claiming that C is
    deficient because it doesn't solve what you see as a problem,
    but trying to force the problem space specifically so that it

    No, /you/ are trying to discredit a simple solution by widening the >goalposts.

    Here we go again. Suffice it to say, no one is trying to
    persecute you. People would take you more seriously if you
    stopped whining about being a victim all the time.

    The main problem being discussed,

    No, that is the problem _you_ are discussing. You're ignoring
    any other problem anyone else points out, and you seem incapable
    of considering that people might be dismissing your proposed
    solution because it doesn't solve enough of a problem, and other
    mechanisms are more general.

    I recognize you are not going to understand, let alone
    appreciate, the distinction here.

    and the one my test fixed, is that of
    'break' being used for two purposes and therefore resulting in clashes
    when Switches and Loops are mixed.

    And what many others in this thread have told you is that that
    is a "problem" that is trivially worked around, that a special
    case for _that problem only_ is not worth it, and that a more
    general solution is being added to the language in C2y.

    What more do you want anyone to say?

    That could easily have been fixed by DMR choosing to use distinct
    keywords. Do you agree so far?

    No. You've described what I consider to be a non-problem; a
    mild annoyance at best, and certainly not something that
    deserves complicating the language for.

    The general category is more interesting, which is what I (and
    probably others) have been trying to tell you. Instead of
    appreciating that a more general solution to the entire category
    of problems, that oh-by-the-way also solves this specific
    problem exists, you instead whine about people moving goalposts.

    No wonder the language never gets better in your view; you can't
    see anything beyond your way of doing things.

    That of breaking out of nested loops is a different problem that would
    need a different solution, and nothing to do with the clash with switch.

    Wrong. The new solution shows that it's actually the same
    solution to the entire category of problems. And that's the
    issue: it doesn't _need_ a different solution.

    It is also one that seems to be about 100 times less common IME.

    ...and yet it's easily solved using the labeled break mechanism
    that is _already in the C2y draft_.

    ...except for all the other cases where it is still awkward and
    solves nothing.

    IT WAS ONLY SUPPOSED TO SOLVE THIS PROBLEM! Namely the issues that
    ensued from DMR overloading 'break'. NOTHING ELSE.

    But that problem is easily solved using labeled breaks.
    Overloading `break` is orthogonal to the solution.

    In fact the confusion between switch-break and loop-break will still be >there even if labels are added.

    I don't know that many C programmers are "confused" by the two
    uses of that single keyword. Certainly, I've seen no evidence
    that such confusion is widespread.

    Unless you've invented a new requirement where you want 'break' within a >>> switch (itself solving an artificial problem) to jump straight to the
    end of an outer switch.

    Yes, that's exactly what I'm saying. Again, you've identified
    one narrow problem,

    It's not that narrow a problem, unless you want to call loops themselves
    a narrow feature.

    It is one that many languages solve for LOOPs by using break or
    equivalent. But they tend not to broaden it either to include breaks out
    of arbitrary kinds of blocks.

    I posted a bunch of languages that use labeled breaks earlier.

    I think this is the central reason people don't take your
    criticism of C particularly seriously.

    I'm sorry but here I don't take yours seriously either. (Have you ever >implemented any of this stuff, or even used such features that you propose?)

    Yes.

    'Jumping to function scope' is poorly defined. Do you mean cutting
    across not only all loops, but any containing nested 'if' and 'switch'
    statements?

    What I mean is this:

    void
    foo(void)
    {
    for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; i++) {
    switch (something) {
    case ...:
    // I want to break out
    // of the switch and
    // both loops here.
    goto label;
    }
    }
    }
    label:
    }

    This example just breaks out of both loops. That the outer one is at >function scope is incidental.

    If the outer loop was contained within an IF statement, could you jump
    to outside that statement using your proposed feature? If not then that
    is not function scope.

    I thought that the context would have made it obvious what I
    meant. I think you are attempting to be pedantic because you
    want to save face by scoring a rhetorical point. Fine, my
    earlier phrasing was poor. Happy?

    With labeled break, this is actually quite clear: `break foo;`
    jumps to the point immediately after the loop or switch
    construct "named" by the label `foo`. Perhaps if you were more
    familiar with the problem space it would have have been clearer.

    I could have done that in C but it would have taken more than 5
    minutes,>> and this was anyway a proof of concept.

    Yup. And it took less than that to point out problems.

    But it solved the problem I wanted to solve! It would solve the problem >Michael S reported! That is, using distinct keywords for two different >things.

    That's the thing: that's not what the fundamental problem is.

    The _actual_ problem is that, because of that and absent some
    more expressive mechanism like a labeled break, you have no way
    to express that you want to leave anything more than the most
    deeply nested level.

    for (;;) {
    int ch = getchar();
    switch (ch) {
    case EOF:
    break; // No way to say break out of the loop.
    case 'a':
    // ...whatever you want to do with 'a'....
    break; // Continue the loop.
    default:
    // whatever....
    break;
    }
    }

    You are fixating on the overloaded keyword as _the problem_ and
    thus intent on addressing that as _the solution_. But there the
    _problem_ is actually more general. Here's how this might be
    addressed using a labeled break:

    loop: for (;;) {
    int ch = getchar();
    switch (ch) {
    case EOF:
    break loop;
    case 'a':
    // whatever.
    break;
    default:
    // whatever.
    break;
    }
    }
    // Control resumes here after `break loop` above.

    See? Problem solved. Along with a bunch of _other_ problems:

    sw: switch (foo) {
    case 'a':
    while ((bar = whatever()) != -1) {
    if (bar == SOMETHING) break sw;
    }
    whatnot();
    break;
    default:
    // etc....
    break;
    }

    I've already used that approach for some decades in my other languages,
    but as I showed in the tables I posted, it is not common, and where
    used, it was always to break out of all loops.

    Anyway, I normally use 'all' instead of a specific number to quit all
    loops. A number works too but I dislike it.

    That sounds overly specific.

    So is breaking out of an inner loop with 'break;'! But it works well as
    it's by far the most common requirement. The next most common IME is to
    quit all loops (like you do in your example).

    In fact, if there are only two nested loops, the inner and outer cover
    all the possibilities.

    ...and all of this can be done with labeled break, which is
    being added to the language.

    Look, bart! Rejoice! The 50 year sin cardinal sin of Ritchie is
    being corrected! Surely you must be simultaneously vindicated
    and elated.

    This is actually the argument against the counted multi-level
    break: if I add or remove a level of nesting, I have to find and
    adjust all of the counts. The labeled break mechanism ties the
    `break` or `continue` to another syntactic element (a label), so

    No, it's just another set of problems as I said.

    Not really.

    You can add new inner loops, delete inner loops, add outer ones, and
    each time you will need to consider whether the labels need to be moved,
    or extra ones added.

    Yup. Welcome to being a programmer. Play your cards right and
    one day you may even graduate to being a software engineer.

    Here's another solution I favour (not implemented), but it only works
    for FOR loops:

    for i in a..b
    for j in c..d
    ... break i

    It's a little like using a label, but here that 'label' is the loop
    index. (This won't work in C as there are no formal loop indices.)

    And with C2y, you can write:

    outer: for (int i = a, i < b; i++) {
    for (int j = c; j < d; j++) {
    // ...
    break outer;
    }
    }
    // We continue here after `break outer`.

    Problem solved.

    if I add or remove a nesting level, I'm still breaking to where
    I had intended to before.

    Yes, but that might now be the wrong loop.

    Yup. But note the difference between "may be" and "will be".
    With counts, it will be. And as I said, none of these
    constructs absolve one of the responsibility to be a competent
    programmer.

    That said, applying the argument to the labeled case is silly.
    Software engineering and good programming practice still matter.
    If you are changing the nested looping structure of your
    program, then you should know where you want to break to;
    presumably your program's behavior depends on it.

    Agreed; see below.

    I'd say the stronger argument for the labeled control structure
    is actually nested switch statements, where I may change a
    series of `if`s to a `switch` with a `case` that contains a
    nested `switch`, or I may change a `switch` to an `if`; if the
    intent is to break out of an enclosing loop, labeled breaks are
    resilient to that, but counted breaks are not.

    You're assuming that the count in indexed breaks includes switch
    statements. It shouldn't; that would be preposterous, and it all still
    comes down to the shared 'break' keyword.

    How about fixing that first, or even admitting it was wrong, before

    That's the thing; it's orthogonal to the root problem. "Admit
    that it was wrong" is the wrong way to look at it. Was it
    weird? I dunno; maybe. Unconventional at the time? I have no
    idea. Fundamentally broken? No.

    Maybe the original set of loop performed some task T, and the new
    loop>> wants to repeat T, in which case it must stay inside.

    Yes.

    Or maybe it is really has to quit ALL loops including any future outer
    ones. Neither labeling or numbering solves this.

    No. If I want to break out of *all* loops, I just make sure
    that the outermost loop is labeled thusly.

    But in my first example, that is not what you want! It all depends.

    As I said, welcome to being a programmer. Hard, isn't it?

    I don't like using multi-level loop exit, it's an untidy feature even
    though I implement it. And I don't like using labeled solutions, as they >just turn them into thinly disguised gotos.

    ALL of these control constructs are "thinly disguised gotos."
    That is the arc of development over time: we started with blunt
    instruments like `goto`, and refined practices to where we have
    identified useful patterns, that we then extract into first
    class constructs of their own.

    This ebbs and flows over time; C++-style exceptions were seen as
    a necessary feature at one point, now many people strive to
    avoid them; Google prohibits their use outright, in a code base
    with billions of lines of code written in that language.

    Labeled loops may also have a new problem with scoping: is the loop name >>> local to this nest of loops, or could an outer loop name especially
    clash with other loop elsewhere?

    Since labels are, you know, labels, they follow the semantics of
    ... labels.

    Careful here: do you really mean that loop-labels will be in the same >name-space as ordinary labels? That means:

    Yes, that's what I mean. Go read the draft standard yourself.

    [snip chest thumping puffery]

    See there's a bit more to this language-design lark!

    Indeed! You demonstrated just how easily it can break down with
    your `breakloop` proposal.

    I've just done a survey in my major apps and haven't found an instance
    where those latter two needed to cross two or more loops.

    Anecdotal evidence, I'm afraid.

    You're welcome to post your own surveys. Although unless the languages
    used in your survey support such features, you may find that hard.

    I'm not the one trying to make the point you are attempting to
    make. You made a claim; the onus is on you to provide evidence
    for that claim.

    It's easy enough to look it up in the draft document; Keith
    posted a link.

    Is that that 793-page document? Perhaps you can summarise how it works!

    I understand; it's a difficult document to follow when you are
    already pre-biased to disregard what it says, as you have
    repeatedly shown yourself to be.

    In this case, it's not too hard, though; the second page says,

    |The following changes were made on or after the 2024
    |September/October Minneapolis, USA meeting:
    |
    | ...about 2/3rds of the way down the list...
    | - N3355: Named/Labeled Loops

    So we can look at N3355 for discussion: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3355.htm

    That's much shorter than the 793-page draft standard. Perhaps
    you'll find it easier to understand.

    This illustrates one reason why changing a language can be hard:
    your idea sounds good at first blush, but it has its own
    deficiencies.

    I appreciate your concern. I've only been doing this (devising and
    implementing systems languages) for 45 years!

    That really doesn't mean anything. Just doing something for a
    long time doesn't mean you're good at it: I have been shooting
    baskets for 45 years, but I will never be a point guard in the
    NBA.

    And yet I've solved all the problems in this thread and many others.

    Congratulations! And yet, despite you being obviously more
    intelligent than all of Ritchie, McIlroy, Thompson, Johnson,
    Kernighan, Plauger, and all of those who have and continue to
    contribute to the development of C combined, we don't see your
    name on the list of contributors to that language, nor does
    anyone other than you use your language.

    But keep shooting hoops, bart. Maybe some day a talent scout
    will see you in your driveway and give you a starting position
    on a playoff team.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@[email protected] (Dan Cross) to comp.lang.c on Wed Oct 14 19:47:22 2026
    From Newsgroup: comp.lang.c

    In article <11aoff0$1n82v$[email protected]>, bart <[email protected]> wrote:
    On 14/10/2026 13:38, Dan Cross wrote:
    In article <11anobe$1dt0e$[email protected]>, bart <[email protected]> wrote:

    Yes, I am aware that you will tell me that it is justified
    because that problem is actually the one worth solving, and the
    others are not; you needn't bother. Simply put, I disagree that
    that one problem is sufficiently important to warrant its own
    solution, particularly when something more general is already
    known and available in the language (labeled break/continue).

    I missed this bit.

    Is labeled break now available in C?

    It's in C2y, and has been implemented in (at least) LLVM/clang
    and GCC. I don't know about other compilers.

    If so, how would it be used here:


    while (1) {
    switch (x) {
    case y:
    Break;

    where that Break is meant to quit the loop.

    term% cat lb.c
    #include <stdio.h>

    int
    main(void)
    {
    int sum = 0;

    outer:
    for (int i = 0; i < 100; i++) {
    for (int j = 0; j < 100; j++) {
    int p = i * j;
    switch (p) {
    case 500:
    break outer;
    default:
    sum += p;
    break;
    }
    }
    }
    printf("sum = %d\n", sum);

    return 0;
    }
    term% clang-23 -std=c2y -o lb lb.c
    term% ./lb
    sum = 235000
    term% gcc-16 -std=c2y -o lb lb.c
    term% ./lb
    sum = 235000
    term% sed 's/outer./\;/' lb.c >lb2.c
    term% clang-23 -std=c2y -o lb2 lb2.c
    term% ./lb2
    sum = 24500500
    term%

    Remember that if DMR hadn't made that screw-up in 1972 it would simply
    have been as it is above with his choice of keyword in place of Break.

    As I said in my other post, you incorrectly assume that that was
    the fundamental issue, when really it's just a detail: the
    problem was that no facility to break out of nested control
    structures as provided. Remedied now!

    But I would be interested in trying out the new feature.

    So do it. You don't need me to hold your hand.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@[email protected] (Dan Cross) to comp.lang.c on Wed Oct 14 19:48:35 2026
    From Newsgroup: comp.lang.c

    In article <11ao8k4$4o6l$[email protected]>,
    Janis Papanagnou <[email protected]> wrote:
    [snip]
    PS: I've just read another long (300 lines) post you made in
    reply to bart. Let me express my admiration for your patience
    and countenance (that I'm clearly lacking in this case), and
    the very clear form and conclusively explained content.

    Thank you! That's very kind of you to say.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Michael S@[email protected] to comp.lang.c on Wed Oct 14 23:28:10 2026
    From Newsgroup: comp.lang.c

    On Wed, 14 Oct 2026 19:30:28 -0000 (UTC)
    [email protected] (Dan Cross) wrote:

    In article <11ao8af$1k8p3$[email protected]>, bart <[email protected]>
    wrote:
    On 14/10/2026 13:38, Dan Cross wrote:
    In article <11anobe$1dt0e$[email protected]>, bart <[email protected]>
    wrote:
    I'd even suggest that using distinct keywords in the original C
    compiler would have made it a tiny bit simpler.)

    Unlikely. I'm trying to chase down the citation, but it was
    known that getting B to fit on the PDP-7 was a challenge. From
    the C history paper,

    Perhaps Switch should have been left out then if it was that tight.

    Why? It's genuinely useful.


    C switch is in the middle between low level construct (computed goto)
    and higher level select/case/whatever of many other languages.
    I suppose that implementing true low level alternative would have been
    simpler for compiler. And it would be even more powerful than current construct. Of course, also more dangerous, but being dangerous is not
    against C philosophy.

    int foo()
    {
    ...
    case 42:
    ....
    switch(bar(x)); // can go not just to 6 and 7, but to 42 as well.
    // if there is no 'default:' in the scope then default ends up here
    ....
    case 6:
    ...
    case 7:
    etc...

    }

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Wed Oct 14 21:56:41 2026
    From Newsgroup: comp.lang.c

    On 14/10/2026 20:30, Dan Cross wrote:
    In article <11ao8af$1k8p3$[email protected]>, bart <[email protected]> wrote:

    Perhaps Switch should have been left out then if it was that tight.

    Why? It's genuinely useful.

    If-else chains can do the same job.

    Sharing a keyword is just crass.

    Don't you share `end`?
    No, that has one meaning which is to terminate a block, there are no repercussions as there are with C-break which has two meanings.

    That could easily have been fixed by DMR choosing to use distinct
    keywords. Do you agree so far?

    No. You've described what I consider to be a non-problem; a
    mild annoyance at best, and certainly not something that
    deserves complicating the language for.

    I'd call it a 'howler'. Even if trivial, it was ludicrously simple to
    avoid, and Michael S wouldn't have needed workarounds or to have waited
    for C2y to be generally available which provides an official workaround.

    Yes, in the simple case of while-switch (see below) it is still
    something extra that is need to overcome that 1972 boo-boo.

    So we can look at N3355 for discussion: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3355.htm

    I found it eventually. But I saw two proposals, I think the other was N3357(?). The difference is that the latter puts the loop label after
    the keyword, so 'for label (' rather than 'label: for (', which makes
    the labels local to the loop, so avoiding the issues below.

    gcc 16.2.0 seems to implement N3355, so the points I made are actually
    true, which is surprising. So here:

    L1:
    while (1) {
    goto L1; // jumps to L1
    continue L1; // jumps to just before }
    break L1; // jumps to just after }
    }

    L1: // error: duplicate label
    while ...

    Meanwhile:

    while (1) {
    if (x == 3)
    break; // this quits the loop as before
    }

    while (1) {
    switch (x) {
    case 3:
    break; // this doesn't break the loop
    }
    }

    So this part hasn't changed. What's changed is that there is a more
    direct workaround:

    loop:
    while (1) {
    switch (x) {
    case 3:
    break loop; // this doesn't break the loop
    }
    }

    Which looks remarkably like the solution I knocked up in 2 minutes:

    while (1) {
    switch (x) {
    case 3:
    breakloop; // this doesn't break the loop
    }
    }

    The difference is, I can consistently use 'breakloop' everywhere: I can duplicate this in the same function. But the 'loop' label is unique to
    that while-loop. (This is what NN3357 or whatever could have fixed.)

    As for multiple nested loops, this will fix that too, that's great. We
    just require some real examples of that being needed!

    And yet I've solved all the problems in this thread and many others.

    Congratulations! And yet, despite you being obviously more
    intelligent than all of Ritchie, McIlroy, Thompson, Johnson,
    Kernighan, Plauger, and all of those who have and continue to
    contribute to the development of C combined,

    Well, my personal C has 'breakloop'! Usually these micro-extensions are shortlived, but I'll keep this one.

    we don't see your
    name on the list of contributors to that language, nor does
    anyone other than you use your language.

    It's enough that I used it and benefited from it.

    This is that last example in my syntax (if the switch were the only
    statement within the loop otherwise two more tokens needed):

    doswitch x
    when 3 then exit
    end

    7 tokens vs. 20 tokens using N3355, and it's repeatable within the
    function because 'exit' is relative.



    But keep shooting hoops, bart. Maybe some day a talent scout
    will see you in your driveway and give you a starting position
    on a playoff team.

    I really don't care. Most things in the world are not going the way I'd
    like, and I'm not the only one who thinks that.

    This language stuff is small potatoes but it gives me kick to have long
    ago come up with solutions that some languages take ... 54 years to
    produce a compromise.

    Anyway, at least you've been a sport, unlike Mr. P.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@[email protected] to comp.lang.c on Wed Oct 14 13:58:53 2026
    From Newsgroup: comp.lang.c

    bart <[email protected]> writes:
    On 14/10/2026 13:38, Dan Cross wrote:
    In article <11anobe$1dt0e$[email protected]>, bart <[email protected]> wrote:

    Yes, I am aware that you will tell me that it is justified
    because that problem is actually the one worth solving, and the
    others are not; you needn't bother. Simply put, I disagree that
    that one problem is sufficiently important to warrant its own
    solution, particularly when something more general is already
    known and available in the language (labeled break/continue).

    I missed this bit.

    How?? I've mentioned it more than once in this thread.

    Is labeled break now available in C?

    It's proposed for C2y, and implemented as an extension in gcc and clang.

    The latest C2y draft is https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3886.pdf

    6.8.2 describes named iteration and switch statements.

    6.8.7.3 and 6.8.7.4 describe the "continue" and "break" statements.

    If so, how would it be used here:

    while (1) {
    switch (x) {
    case y:
    Break;

    where that Break is meant to quit the loop.

    I have no doubt that you can figure it out after reading the cited
    sections. (I'm not sure why you spelled "break" with an uppercase 'B'.)

    [...]

    Elsewhere, you've mentioned that labels have function scope.
    That's not a problem. A named "break" or "continue" can only
    refer to the label of an enclosing iteration or switch statement.
    "break FOO;" where FOO does not apply to an enclosing loop or switch
    is a constraint violation. But "goto FOO;" is valid as long as
    "FOO:" is within the same function (with some restrictions that
    aren't relevant here).
    --
    Keith Thompson (The_Other_Keith) [email protected]
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Wed Oct 14 21:59:37 2026
    From Newsgroup: comp.lang.c

    On 14/10/2026 21:56, bart wrote:
    On 14/10/2026 20:30, Dan Cross wrote:

                break loop;      // this doesn't break the loop

                breakloop;      // this doesn't break the loop

    Ignore those comments, which are not true!


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@[email protected] to comp.lang.c on Wed Oct 14 14:23:29 2026
    From Newsgroup: comp.lang.c

    bart <[email protected]> writes:
    [...]
    But as Keith pointed out, W14 is now entertaining proposals to
    add labeled `break` to the language. I haven't looked myself,
    but if that is usable in a `switch` context, then it would solve
    the problem for good.

    OK. Although in that form, it really is little different from
    'goto'. I believe the main difference is that the label goes at the
    beginning of the loop rather than the end!

    Hardly.

    Like most or all "structured" control flow constructs, it's a kind of restricted goto -- and it's the restrictions that make it useful in
    writing clear code.

    "break", with or without a label, can only jump forward. That makes it
    much more difficult to use it to write spaghetti code.

    Yes, "break FOO;" is equivalent to a goto, given an appropriately placed
    label. So what?

    FOO:
    for (blah;blah;blah) {
    BAR:
    while (blah) {
    if (cond1) {
    break FOO;
    }
    else if (cond2) {
    break BAR;
    }
    }
    }

    "break FOO" is implemented as a jump to a point just after the end
    of the outer loop. But the way I think of it is that "FOO" is the
    name of the entire outer loop, not just a single point in the code.
    "break FOO;" applies to the named loop, causing execution of the
    loop to terminate. The fact that it's equivalent to a goto (just
    as "break;" is) is an implementation detail.

    One very minor infelicity is that the same syntax is used for labels
    intended to be the targets of gotos and labels intended to name
    loops and switch statements. I think this same issue occurs in
    most languages that have named breaks. (Ada is an exception; it
    uses a deliberately heavy syntax for goto labels, "<<LABEL>>", and
    a simpler syntax for loop names, "NAME:". But Ada had both gotos
    and named loops from the begining.) There has been a proposal to
    use a different syntax for named loops ("for NAME (;;)"), but it's
    not reflected in the latest C2y draft. The fact that a loop name
    can also be used as the target of a goto is a trivial problem,
    perhaps a non-problem, solved by just not doing that.

    And maybe those scoping rules will be different: goto labels have function-wide scope.

    See the C2y draft.

    [...]
    --
    Keith Thompson (The_Other_Keith) [email protected]
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@[email protected] (Dan Cross) to comp.lang.c on Thu Oct 15 01:26:35 2026
    From Newsgroup: comp.lang.c

    In article <11aoqa9$1rgda$[email protected]>, bart <[email protected]> wrote:
    On 14/10/2026 20:30, Dan Cross wrote:
    [snip more of the same already hashed and rehashed ad naseum]

    As for multiple nested loops, this will fix that too, that's great. We
    just require some real examples of that being needed!

    Here's a pretty terrible way to write part of a lexical
    analyzer. I just typed this in an hour or so ago.

    #include <ctype.h>
    #include <stddef.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>

    static size_t lineno = 1;
    static size_t colno = 0;

    #define MAXTOKLEN 1024

    typedef enum TokenType TokenType;
    enum TokenType {
    TkERROR = -1,
    TkEOF = 0,

    TkSTAR = '*',
    TkSLASH = '/',
    TkPLUS = '+',
    TkMINUS = '-',

    TkLT = '<',
    TkGT = '>',
    TkEQ = '=',
    TkBANG = '!',

    TkGE = 0x1000,
    TkLE,
    TkSTRING,
    TkIDENT,
    // etc....
    };

    typedef struct Token Token;
    struct Token {
    TokenType type;
    char *token;
    };

    Token *
    newtoken(TokenType tt, char *s, char *e)
    {
    size_t len = sizeof(Token) + (e - s) + 1 + (e == s);
    Token *token = malloc(len);
    if (token == NULL) abort();
    memset(token, 0, len);
    token->type = tt;
    token->token = (char *)token + sizeof(*token);
    token->token[0] = tt;
    if (e != s)
    memcpy(token->token, s, e - s);
    return token;
    }

    static int
    peek(FILE *fp)
    {
    int ch = fgetc(fp);
    if (ch != EOF)
    ungetc(ch, fp);
    return ch;
    }

    Token *
    nexttoken(FILE *fp)
    {
    char tokstr[MAXTOKLEN], *tp = tokstr, *te = tokstr + MAXTOKLEN - 1;
    enum TokenType tt = TkEOF;
    Token *next = NULL;
    int ch;
    unsigned char c;

    loop:
    while ((ch = fgetc(fp)) != EOF) {
    tt = TkERROR;
    ++colno;
    switch (ch) {
    case '\n':
    ++lineno;
    colno = 0;
    case ' ':
    case '\t':
    case '\f':
    case '\v':
    case '\r':
    break;
    case '*':
    tt = TkSTAR;
    break loop;
    case '/':
    tt = TkSLASH;
    ch = peek(fp);
    switch (ch) {
    case EOF:
    break loop;
    case '/':
    while ((ch = fgetc(fp)) != '\n')
    if (ch == EOF)
    break loop;
    ungetc(ch, fp);
    continue;
    default:
    break;
    }
    break loop;
    case '+':
    tt = TkPLUS;
    break loop;
    case '-':
    tt = TkMINUS;
    break loop;
    case '<':
    tt = TkLT;
    *tp++ = '<';
    ch = peek(fp);
    switch (ch) {
    case EOF:
    break loop;
    case '=':
    tt = TkLE;
    *tp++ = '=';
    break;
    default:
    break;
    }
    *tp++ = '\0';
    break loop;
    case '>':
    tt = TkGT;
    *tp++ = '>';
    ch = peek(fp);
    switch (ch) {
    case EOF:
    break loop;
    case '=':
    tt = TkGE;
    *tp++ = '=';
    break;
    default:
    break;
    }
    *tp++ = '\0';
    break loop;
    case '=':
    tt = TkEQ;
    break loop;
    case '!':
    tt = TkBANG;
    break loop;
    case '"':
    tt = TkERROR;
    sloop:
    while (tp != te) {
    ch = fgetc(fp);
    switch (ch) {
    case EOF:
    break loop;
    case '"':
    break sloop;

    case '\\':
    ch = fgetc(fp);
    switch (ch) {
    case EOF:
    break loop;
    case 'n':
    ch = '\n';
    break;
    case 'r':
    ch = '\r';
    break;
    case 't':
    ch = '\t';
    break;
    default:
    break;
    }
    default:
    *tp++ = ch;
    break;
    }
    }
    *tp++ = '\0';
    tt = TkSTRING;
    break loop;
    default:
    c = ch;
    if (c != '_' && !isalnum(c))
    break loop;
    *tp++ = c;
    while (tp != te) {
    ch = fgetc(fp);
    if (ch == EOF)
    break loop;
    c = ch;
    if (c != '_' && !isalnum(c)) {
    ungetc(ch, fp);
    break;
    }
    *tp++ = c;
    }
    *tp++ = '\0';
    tt = TkIDENT;
    break loop;
    }
    }
    next = newtoken(tt, tokstr, tp);
    return next;
    }

    int
    main(void)
    {
    Token *tok;
    while ((tok = nexttoken(stdin)) != NULL) {
    if (tok->type == TkEOF)
    break;
    if (tok->type != TkERROR)
    printf("tok: tt = %x, token = '%s'\n", tok->type, tok->token);
    free(tok);
    }
    return 0;
    }

    And yet I've solved all the problems in this thread and many others.

    Congratulations! And yet, despite you being obviously more
    intelligent than all of Ritchie, McIlroy, Thompson, Johnson,
    Kernighan, Plauger, and all of those who have and continue to
    contribute to the development of C combined,

    Well, my personal C has 'breakloop'! Usually these micro-extensions are >shortlived, but I'll keep this one.

    Consider that perhaps your obstinance about keeping this sort
    of poorly thought-through extension is WHY no one but you uses
    your stuff.

    we don't see your
    name on the list of contributors to that language, nor does
    anyone other than you use your language.

    It's enough that I used it and benefited from it.

    This is that last example in my syntax (if the switch were the only >statement within the loop otherwise two more tokens needed):

    doswitch x
    when 3 then exit
    end

    7 tokens vs. 20 tokens using N3355, and it's repeatable within the
    function because 'exit' is relative.

    Ok. Don't really care.

    But keep shooting hoops, bart. Maybe some day a talent scout
    will see you in your driveway and give you a starting position
    on a playoff team.

    I really don't care. Most things in the world are not going the way I'd >like, and I'm not the only one who thinks that.

    This language stuff is small potatoes but it gives me kick to have long
    ago come up with solutions that some languages take ... 54 years to
    produce a compromise.

    Anyway, at least you've been a sport, unlike Mr. P.

    *shrug*

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Tim Rentsch@[email protected] to comp.lang.c on Wed Oct 14 21:30:03 2026
    From Newsgroup: comp.lang.c

    Michael S <[email protected]> writes:

    On Wed, 14 Oct 2026 19:30:28 -0000 (UTC)
    [email protected] (Dan Cross) wrote:

    In article <11ao8af$1k8p3$[email protected]>, bart <[email protected]>
    wrote:

    On 14/10/2026 13:38, Dan Cross wrote:

    In article <11anobe$1dt0e$[email protected]>, bart <[email protected]>
    wrote:

    I'd even suggest that using distinct keywords in the original C
    compiler would have made it a tiny bit simpler.)

    Unlikely. I'm trying to chase down the citation, but it was
    known that getting B to fit on the PDP-7 was a challenge. From
    the C history paper,

    Perhaps Switch should have been left out then if it was that tight.

    Why? It's genuinely useful.

    C switch is in the middle between low level construct (computed goto)
    and higher level select/case/whatever of many other languages.
    I suppose that implementing true low level alternative would have been simpler for compiler. And it would be even more powerful than current construct. Of course, also more dangerous, but being dangerous is not against C philosophy.

    int foo()
    {
    ...
    case 42:
    ....
    switch(bar(x)); // can go not just to 6 and 7, but to 42 as well.
    // if there is no 'default:' in the scope then default ends up here
    ....
    case 6:
    ...
    case 7:
    etc...

    }

    I'm reminded of a quote from E.W. Dijkstra:

    "No, gentlemen. Three times no."
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@[email protected] to comp.lang.c on Thu Oct 15 12:08:55 2026
    From Newsgroup: comp.lang.c

    On 2026-10-14 22:58, Keith Thompson wrote:
    bart <[email protected]> writes:
    On 14/10/2026 13:38, Dan Cross wrote:
    In article <11anobe$1dt0e$[email protected]>, bart <[email protected]> wrote:

    Yes, I am aware that you will tell me that it is justified
    because that problem is actually the one worth solving, and the
    others are not; you needn't bother. Simply put, I disagree that
    that one problem is sufficiently important to warrant its own
    solution, particularly when something more general is already
    known and available in the language (labeled break/continue).

    I missed this bit.

    How??

    If operating one's intellect in a batten-down-the-hatches mode,
    or if a brain is working in /dev/null mode, are two possibilities
    that occur to me to miss that. I also see the possibility that in
    a heated discussion one might be tempted to prioritize a rebuttal
    in a post without beforehand taking the time thinking about the
    provided information. (Although the former two possibilities seem
    more likely in this case.)

    I've mentioned it more than once in this thread.

    A couple other posters as well.

    Janis

    [...]

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Thu Oct 15 12:01:51 2026
    From Newsgroup: comp.lang.c

    On 15/10/2026 02:26, Dan Cross wrote:
    In article <11aoqa9$1rgda$[email protected]>, bart <[email protected]> wrote:
    On 14/10/2026 20:30, Dan Cross wrote:
    [snip more of the same already hashed and rehashed ad naseum]

    As for multiple nested loops, this will fix that too, that's great. We
    just require some real examples of that being needed!

    Here's a pretty terrible way to write part of a lexical
    analyzer. I just typed this in an hour or so ago.
    ....


    Wow, it's impressive that you went to that trouble just to prove a point
    about nested loops. (Even if it might have been a little bit contrived.)

    But this is an interesting pattern with all those breaks:

    break;
    break loop;
    break loop;
    break loop;
    break;
    break loop;
    break loop;
    break loop;
    break loop;
    break;
    break;
    break loop;
    break loop;
    break;
    break;
    break loop;
    break loop;
    break loop;
    break loop;
    break sloop;
    break loop;
    break;
    break;
    break;
    break;
    break;
    break loop;
    break loop;
    break loop;
    break; // loop
    break loop;
    break; // loop

    It seems most uses of 'break;' to break out of a loop have disappeared
    to be replaced with labeled versions.

    The remaining breaks are switch-breaks.

    Then I start looking at some of those "breaks;". Some (maybe one) is at top-level, it jumps to the end of that switch, so the end of the while,
    so is really 'continue'.

    Most are in nested switches, some of those jump to a 'break loop'. Some
    jump somewhere else...

    Basically this is spaghetti code (I know you said it was terrible); your
    eyes glaze over with breaks everywhere and you give up trying to figure
    out the control flow.

    There are examples like this:

    continue;
    default:
    break;
    }
    break loop;

    Do you even need 'default: break;}' or even an empty default:?

    I then tried an experiment where I got rid of switch-break, to see what
    C code with automatic switch-break would look like.

    It was a big improvement, now that you know that every case-blocks
    proceeds to the end of that switch, and you don't need to double-check
    every 'break' to see if it's to do with switches or loops:

    break loop;
    break loop;
    break loop;
    break loop;
    break loop;
    break loop;
    break loop;
    break loop;
    break loop;
    break loop;
    break loop;
    break loop;
    break loop;
    break sloop;
    break loop;
    break loop;
    break loop;
    break loop;
    break;
    break loop;
    break;

    All these are known to be loops, even 'break;'.

    But also, labeled versions except three 'break loops' can be written as 'break', since 'switch break' does not exist. You're left with:

    break loop;
    break loop;
    break loop;
    break;
    break;
    break;
    break;
    break;
    break;
    break;
    break;
    break;
    break;
    break;
    break;
    break;
    break;
    break;
    break;
    break;
    break;

    (Not ordered.) Compare with the first set.

    [snip more of the same already hashed and rehashed ad naseum]

    Perhaps that reused keyword thing is a bigger deal than you think. The
    effect of it is unnecessary obfuscation.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@[email protected] (Dan Cross) to comp.lang.c on Thu Oct 15 11:45:33 2026
    From Newsgroup: comp.lang.c

    In article <11aqbqv$2avn3$[email protected]>, bart <[email protected]> wrote:
    On 15/10/2026 02:26, Dan Cross wrote:
    In article <11aoqa9$1rgda$[email protected]>, bart <[email protected]> wrote:
    On 14/10/2026 20:30, Dan Cross wrote:
    [snip more of the same already hashed and rehashed ad naseum]

    As for multiple nested loops, this will fix that too, that's great. We
    just require some real examples of that being needed!

    Here's a pretty terrible way to write part of a lexical
    analyzer. I just typed this in an hour or so ago.
    ....

    Wow, it's impressive that you went to that trouble just to prove a point >about nested loops. (Even if it might have been a little bit contrived.)

    But this is an interesting pattern with all those breaks:

    [snip]

    It seems most uses of 'break;' to break out of a loop have disappeared
    to be replaced with labeled versions.

    The remaining breaks are switch-breaks.

    Then I start looking at some of those "breaks;". Some (maybe one) is at >top-level, it jumps to the end of that switch, so the end of the while,
    so is really 'continue'.

    Most are in nested switches, some of those jump to a 'break loop'. Some
    jump somewhere else...

    Basically this is spaghetti code (I know you said it was terrible); your >eyes glaze over with breaks everywhere and you give up trying to figure
    out the control flow.

    Perhaps if I had spent more than like, 30 minutes, on it I would
    have tidied it up. The point was to illustrate a contrived
    example where one might break out of nested switch statements,
    loops inside of switch, switch inside of loops, loops inside of
    switch inside of loops, and so on.

    There are examples like this:

    continue;
    default:
    break;
    }
    break loop;

    Do you even need 'default: break;}' or even an empty default:?

    You don't, but some compilers will complain if it isn't there.
    See above. It was merely a quick and dirty example.

    I then tried an experiment where I got rid of switch-break, to see what
    C code with automatic switch-break would look like.

    It was a big improvement, now that you know that every case-blocks
    proceeds to the end of that switch, and you don't need to double-check
    every 'break' to see if it's to do with switches or loops:

    break loop;
    break loop;
    break loop;
    break loop;
    break loop;
    break loop;
    break loop;
    break loop;
    break loop;
    break loop;
    break loop;
    break loop;
    break loop;
    break sloop;
    break loop;
    break loop;
    break loop;
    break loop;
    break;
    break loop;
    break;

    All these are known to be loops, even 'break;'.

    But also, labeled versions except three 'break loops' can be written as >'break', since 'switch break' does not exist. You're left with:

    break loop;
    break loop;
    break loop;
    break;
    break;
    break;
    break;
    break;
    break;
    break;
    break;
    break;
    break;
    break;
    break;
    break;
    break;
    break;
    break;
    break;
    break;

    (Not ordered.) Compare with the first set.

    Compare what? Without the surrounding context, this is utterly
    meaningless: this isn't a useful illustration of working code;
    this is the output of `grep`.

    (btw, if you `|sort |uniq -c` you can actually get counts! You
    can even `|sort |uniq -c |sort -n` to order by frequency of
    occurrence!)

    [snip more of the same already hashed and rehashed ad naseum]

    Perhaps that reused keyword thing is a bigger deal than you think. The >effect of it is unnecessary obfuscation.

    This is certainly not evidence of that. This is just your
    assertion that you took a silly example and apparently (maybe?)
    improved it, based on some unstated, but apparently subjective,
    criteria.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Tim Rentsch@[email protected] to comp.lang.c on Thu Oct 15 05:17:10 2026
    From Newsgroup: comp.lang.c

    [email protected] (Dan Cross) writes:

    In article <11aoqa9$1rgda$[email protected]>, bart <[email protected]> wrote:

    On 14/10/2026 20:30, Dan Cross wrote:
    [snip more of the same already hashed and rehashed ad naseum]

    As for multiple nested loops, this will fix that too, that's great. We
    just require some real examples of that being needed!

    Here's a pretty terrible way to write part of a lexical
    analyzer. I just typed this in an hour or so ago.

    [200+ lines of code]

    This code provides an excellent example of why multi-level breaks
    should not be added to C. The code would be easier to understand
    if all the 'break <label>;' lines were replaced with one of 'goto TOKEN_COMPLETE;' or 'goto COMMENT_COMPLETE;', as appropriate,
    and with the loop labels being removed and the two new labels put
    in at the appropriate places.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@[email protected] (Dan Cross) to comp.lang.c on Thu Oct 15 14:37:13 2026
    From Newsgroup: comp.lang.c

    In article <[email protected]>,
    Tim Rentsch <[email protected]> wrote:
    [email protected] (Dan Cross) writes:

    In article <11aoqa9$1rgda$[email protected]>, bart <[email protected]> wrote:

    On 14/10/2026 20:30, Dan Cross wrote:
    [snip more of the same already hashed and rehashed ad naseum]

    As for multiple nested loops, this will fix that too, that's great. We
    just require some real examples of that being needed!

    Here's a pretty terrible way to write part of a lexical
    analyzer. I just typed this in an hour or so ago.

    [200+ lines of code]

    This code provides an excellent example of why multi-level breaks
    should not be added to C.

    It is probably true that this snippet is a good example of how
    labeled break/continue can be abused. The code is awful.

    However, the current C2y draft standard already has labeled
    break and continue; the probability that it won't make it into
    the next standard revision is low.

    Moreover, other languages have had it for years (in some cases,
    decades) at this point and the sky has not fallen. One bad
    example, meant only to illustrate a couple of use cases, should
    not be used as evidence either way to draw a general conclusion
    about, well, anything.

    The code would be easier to understand
    if all the 'break <label>;' lines were replaced with one of 'goto >TOKEN_COMPLETE;' or 'goto COMMENT_COMPLETE;', as appropriate,
    and with the loop labels being removed and the two new labels put
    in at the appropriate places.

    Whenever one says that, "the code would be easier to understand"
    one is necessarily making a subjective judgement.

    In this case, _I_ think that code would be far easier to
    understand written in an entirely different way that didn't
    reach for `goto` at all.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Thu Oct 15 15:57:38 2026
    From Newsgroup: comp.lang.c

    On 15/10/2026 12:45, Dan Cross wrote:
    In article <11aqbqv$2avn3$[email protected]>, bart <[email protected]> wrote:

    Perhaps that reused keyword thing is a bigger deal than you think. The
    effect of it is unnecessary obfuscation.

    This is certainly not evidence of that. This is just your
    assertion that you took a silly example and apparently (maybe?)
    improved it, based on some unstated, but apparently subjective,
    criteria.
    I am stating that 'break' used to fix C's poor 'switch' feature
    interferes with 'break' used for loops.

    It's not even my opinion: it's fact. In your example, about a third of
    'break' tokens are for taking care of switch.

    My opinion is that it generates pointless clutter (this it would do even
    if a different keyword was used), and it can get confusing when switch
    and loop are mixed up.

    I actually took your program and ported it to my syntax, as I was
    curious how it would look. This is the result:

    https://github.com/bart-2026/langs/blob/main/lexertest.m

    (It's been spaced out more, vertically.)

    There were some tricky bits of the C to translate, such as:

    break;
    default:
    break;
    }
    default:
    *tp++ = ch;
    break;
    }
    }
    *tp++ = '\0';
    tt = TkSTRING;

    where it seems to break from one switch then sneakily falls through into
    the default clauses of the enclosing one!

    Well, here are some stats:

    C Mine

    Size 3374 2997 characters (both with hard tabs)
    Non-blank lines 210 174 Lines


    I did try and run mine:

    c:\mapps>test
    1234
    tok: tt = tkident, token = '1234'
    abc
    tok: tt = tkident, token = 'abc'

    It shows both of these as an identifier. But yours does the same:

    c:\c>a
    1234
    tok: tt = 1003, token = '1234'
    abc
    tok: tt = 1003, token = 'abc'

    Whatever '1003' means, it's showing the same. So it will do (I don't
    care if the code is buggy, just whether my version is reasonably faithful).

    Of course, my actual lexers have a different structure.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Thu Oct 15 18:10:37 2026
    From Newsgroup: comp.lang.c

    On 15/10/2026 15:57, bart wrote:
    On 15/10/2026 12:45, Dan Cross wrote:
    In article <11aqbqv$2avn3$[email protected]>, bart  <[email protected]> wrote:

    Perhaps that reused keyword thing is a bigger deal than you think. The
    effect of it is unnecessary obfuscation.

    This is certainly not evidence of that.  This is just your
    assertion that you took a silly example and apparently (maybe?)
    improved it, based on some unstated, but apparently subjective,
    criteria.
    I am stating that 'break' used to fix C's poor 'switch' feature
    interferes with 'break' used for loops.

    It's not even my opinion: it's fact. In your example, about a third of 'break' tokens are for taking care of switch.

    My opinion is that it generates pointless clutter (this it would do even
    if a different keyword was used), and it can get confusing when switch
    and loop are mixed up.

    I actually took your program and ported it to my syntax, as I was
    curious how it would look. This is the result:

    https://github.com/bart-2026/langs/blob/main/lexertest.m

    (It's been spaced out more, vertically.)

    Well, here are some stats:

    I did try and run mine:
    Enough worked that I decided to try a speed test. Both use exactly the
    same algorithm, and I didn't expect either to be fast.

    Still, the version in my language/compiler was 50% faster than the C
    compiled with gcc-O3. I don't know why.

    (My production lexers, even in my language so unoptimised, tend to be at
    least a magnitude faster and do more stuff such as symbol table lookups.)
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@[email protected] to comp.lang.c on Thu Oct 15 20:50:46 2026
    From Newsgroup: comp.lang.c

    On 2026-10-15 16:37, Dan Cross wrote:
    In article <[email protected]>,
    Tim Rentsch <[email protected]> wrote:
    [...]

    It is probably true that this snippet is a good example of how
    labeled break/continue can be abused. [...]

    Else-thread (in a reply to bart) you had already written:

    The point was to illustrate a contrived
    example where one might break out of nested switch statements,
    loops inside of switch, switch inside of loops, loops inside of
    switch inside of loops, and so on.

    In a newsgroup (also generally) where part of the audience isn't
    interested in understanding the context and intention of such
    examples it's "good" fodder for those to continue their campaign.

    Of course your example with its intent were obvious and clear.
    Your formerly posted explanations without code had already been
    clear. (I.e., for those that were interested to understand the
    point. For those that aren't, with every additional post, and
    especially with lots of code, you just feed the... - campaigners.
    Wasted time, IMO.)

    Janis

    [...]

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Thu Oct 15 19:59:54 2026
    From Newsgroup: comp.lang.c

    On 15/10/2026 13:17, Tim Rentsch wrote:
    [email protected] (Dan Cross) writes:

    In article <11aoqa9$1rgda$[email protected]>, bart <[email protected]> wrote:

    On 14/10/2026 20:30, Dan Cross wrote:
    [snip more of the same already hashed and rehashed ad naseum]

    As for multiple nested loops, this will fix that too, that's great. We
    just require some real examples of that being needed!

    Here's a pretty terrible way to write part of a lexical
    analyzer. I just typed this in an hour or so ago.

    [200+ lines of code]

    This code provides an excellent example of why multi-level breaks
    should not be added to C.

    Actually most of those 'break-labels' are not multi-level breaks.

    But they have to use that form because they are inside 'switch'.

    (Unless you consider 'levels' to include switch statements as loops; I
    don't. I mean, there is a 'continue' in there too inside switch, which
    doesn't use the label. So how can that not be multi-level but 'break' is?)

    It all goes back to that bad decision about 'break' that everyone is
    playing down.




    The code would be easier to understand
    if all the 'break <label>;' lines were replaced with one of 'goto TOKEN_COMPLETE;' or 'goto COMMENT_COMPLETE;', as appropriate,
    and with the loop labels being removed and the two new labels put
    in at the appropriate places.


    Once you have to write /actual labels/, which aren't even in local scope within the loop, then 'break label' doesn't buy much over 'goto label':

    loop:
    while () {
    switch () {
    case x:
    break loop;
    }
    }

    while () {
    switch () {
    case x:
    goto loopend;
    }
    }
    loopend:

    The latter will at least work with every compiler.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@[email protected] (Dan Cross) to comp.lang.c on Thu Oct 15 20:42:53 2026
    From Newsgroup: comp.lang.c

    In article <11aqpl3$2gdup$[email protected]>, bart <[email protected]> wrote:
    On 15/10/2026 12:45, Dan Cross wrote:
    In article <11aqbqv$2avn3$[email protected]>, bart <[email protected]> wrote:

    Perhaps that reused keyword thing is a bigger deal than you think. The
    effect of it is unnecessary obfuscation.

    This is certainly not evidence of that. This is just your
    assertion that you took a silly example and apparently (maybe?)
    improved it, based on some unstated, but apparently subjective,
    criteria.

    I am stating that 'break' used to fix C's poor 'switch' feature
    interferes with 'break' used for loops.

    Sure.

    It's not even my opinion: it's fact. In your example, about a third of >'break' tokens are for taking care of switch.

    Ok.

    My opinion is that it generates pointless clutter (this it would do even
    if a different keyword was used), and it can get confusing when switch
    and loop are mixed up.

    Ok.

    I actually took your program and ported it to my syntax, as I was
    curious how it would look. This is the result:

    https://github.com/bart-2026/langs/blob/main/lexertest.m

    (It's been spaced out more, vertically.)

    There were some tricky bits of the C to translate, such as:

    break;
    default:
    break;
    }
    default:
    *tp++ = ch;
    break;
    }
    }
    *tp++ = '\0';
    tt = TkSTRING;

    where it seems to break from one switch then sneakily falls through into
    the default clauses of the enclosing one!

    Yup.

    Well, here are some stats:

    C Mine

    Size 3374 2997 characters (both with hard tabs)
    Non-blank lines 210 174 Lines

    Those seem like pretty meaningless statistics. I could really
    care less about 377 fewer bytes. Naturally, different languages
    will express these things differently.

    I did try and run mine:

    c:\mapps>test
    1234
    tok: tt = tkident, token = '1234'
    abc
    tok: tt = tkident, token = 'abc'

    It shows both of these as an identifier. But yours does the same:

    c:\c>a
    1234
    tok: tt = 1003, token = '1234'
    abc
    tok: tt = 1003, token = 'abc'

    Yup. It's a poorly written program; I am not surprised there
    are bugs. It wasn't meant to be an illustration of exemplary
    programming, it was meant to illustrate a use case for a
    language construct that addresses a use case you appeared to
    want support for, but that are now upset about, because it was
    not provided in the way you like. Or something.

    Whatever '1003' means, it's showing the same. So it will do (I don't
    care if the code is buggy, just whether my version is reasonably faithful).

    This is actually a good example of the problem you often run
    into in these endless c.l.c threads: You seem to take a thing
    that was something that was only meant to show one thing, and
    asserting that it represents something other than what it was
    meant to show, and no matter how many times it is explained to
    you that it is not, in fact, what you seem to think that it is,
    you persist in your delusion and think that it proves something.
    But it doesn't, since you are starting from a false premise, at
    which point you whine that you are picked on, treated poorly,
    misunderstood, or generally dismissed, to which you conclude
    that this can only be due to a slavish devotion to C as it is,
    and a refusal to entertain that the language is not perfect. It
    is totally lost on you that people may be objecting to what you
    are saying on its own merits, since (ironically) you don't seem
    able to admit that your own ideas may have their own
    deficiencies.

    This whole discussion could be summarized as:

    Bart: "C sucks because Dennis Ritchie stupidly reused `break`
    for both loops and switch. He was a tasteless fool."
    All: "You can work around that really easily."
    Keith: "C added labeled break and continue...."
    Bart: "C sucks. My language is better. Here, I fixed C in 4
    lines of code with my `breakloop`, but it still sucks
    because C is hopeless."
    Me: "No, the real problem is that there's no structured way
    break out of nested contexts; your thing only addresses
    one special case, and does not compose, so can't cover
    the general case."
    Bart: "No, it's the overloading. C is terrible and you're all
    just too blind to see it. You are all fools, like
    Dennis Ritchie."
    Me: "I mean, Keith told you how the language is being changed
    to address your problem _and_ the other problems in this
    general category."
    Bart: "Those other problems don't matter. C will never change.
    It will suck forever. I mean, have you ever even seen a
    use case for these labeled blocks? I don't like them,
    therefore they suck, just like C. They also suck
    because they solve a problem I don't care about. I have
    been doing this for 45 years."
    Me: "Here's a program that illustrates the problem. The code
    is shit, but shows how it can be used...."
    Bart: "This program sucks! You don't _need_ to do it this
    way."
    Me: "...I mean, I told you it sucked when I posted it...."
    Bart: "...I rewrote it in my language. I saved 377 bytes. See
    how much C sucks now? My language is better.
    Me: "...."
    Bart: "My lexer is 50% faster than your lexer. My production
    code is an order of magnitude faster. I am a very smart
    boy, and deserve a very special gold star on my report
    card."
    Me: "...Bruh."
    Bart: "Dennis Ritchie was a fool. A fool, I say! Haha!
    Ahahaha! Muwhahaha!"

    Of course, my actual lexers have a different structure.

    If I actually wanted a real lexer for C, I'd probably use a
    lexer generator to generate one from a declarative description
    of the language's lexemes.

    Now then. Did you see how it used labeled break and continue to
    move about through the various control structures in ways that
    would not be representable if you only had `breakloop`? Yes, of
    course you can restructure the code, but that's not the point;
    the point was only to show how one might use labeled loops and
    switches and so on to implement control flows that one cannot
    express _without_ such facil

    The irony is that you are saying, in effect, "oh but you don't
    actually _need_ to do it that way..." to something you don't
    care for, when throughout the thread you have been specifically
    rejecting that same argument as a response your assertion that
    something that addressed this very use case was badly needed, to
    fix Dennis Ritchie's "mistake" of using `break` for both loops
    and `switch`. Seriously. The stunning lack of self-awareness
    is really quite breathtaking.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@[email protected] (Dan Cross) to comp.lang.c on Thu Oct 15 20:49:13 2026
    From Newsgroup: comp.lang.c

    In article <11ar7rb$2mb01$[email protected]>, bart <[email protected]> wrote:
    On 15/10/2026 13:17, Tim Rentsch wrote:
    [email protected] (Dan Cross) writes:

    In article <11aoqa9$1rgda$[email protected]>, bart <[email protected]> wrote: >>>
    On 14/10/2026 20:30, Dan Cross wrote:
    [snip more of the same already hashed and rehashed ad naseum]

    As for multiple nested loops, this will fix that too, that's great. We >>>> just require some real examples of that being needed!

    Here's a pretty terrible way to write part of a lexical
    analyzer. I just typed this in an hour or so ago.

    [200+ lines of code]

    This code provides an excellent example of why multi-level breaks
    should not be added to C.

    Actually most of those 'break-labels' are not multi-level breaks.

    But they have to use that form because they are inside 'switch'.

    (Unless you consider 'levels' to include switch statements as loops; I >don't. I mean, there is a 'continue' in there too inside switch, which >doesn't use the label. So how can that not be multi-level but 'break' is?)

    It all goes back to that bad decision about 'break' that everyone is
    playing down.

    The code would be easier to understand
    if all the 'break <label>;' lines were replaced with one of 'goto
    TOKEN_COMPLETE;' or 'goto COMMENT_COMPLETE;', as appropriate,
    and with the loop labels being removed and the two new labels put
    in at the appropriate places.


    Once you have to write /actual labels/, which aren't even in local scope >within the loop, then 'break label' doesn't buy much over 'goto label':

    loop:
    while () {
    switch () {
    case x:
    break loop;
    }
    }

    while () {
    switch () {
    case x:
    goto loopend;
    }
    }
    loopend:

    The latter will at least work with every compiler.

    I mentioned this already; labeled continue and labeled break
    both consume only one label; `goto` would require two:

    outer:
    for (i = 0; i < n; i++)
    for (j = 0; j < m; j++)
    if (condx(i, j)) break outer;
    else if (condy(i, j)) continue outer;

    vs:

    for (i = 0; i < n; i++) {
    for (j = 0; j < m; j++)
    if (condx(i, j)) goto outer_break;
    else if (condy(i, j)) goto outer_continue;

    outer_continue:
    }
    outer_break:

    And so forth.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Michael S@[email protected] to comp.lang.c on Thu Oct 15 23:57:52 2026
    From Newsgroup: comp.lang.c

    On Thu, 15 Oct 2026 20:42:53 -0000 (UTC)
    [email protected] (Dan Cross) wrote:

    In article <11aqpl3$2gdup$[email protected]>, bart <[email protected]>
    wrote:
    On 15/10/2026 12:45, Dan Cross wrote:
    In article <11aqbqv$2avn3$[email protected]>, bart <[email protected]>
    wrote:

    Perhaps that reused keyword thing is a bigger deal than you
    think. The effect of it is unnecessary obfuscation.

    This is certainly not evidence of that. This is just your
    assertion that you took a silly example and apparently (maybe?)
    improved it, based on some unstated, but apparently subjective,
    criteria.

    I am stating that 'break' used to fix C's poor 'switch' feature
    interferes with 'break' used for loops.

    Sure.

    It's not even my opinion: it's fact. In your example, about a third
    of 'break' tokens are for taking care of switch.

    Ok.

    My opinion is that it generates pointless clutter (this it would do
    even if a different keyword was used), and it can get confusing when
    switch and loop are mixed up.

    Ok.

    I actually took your program and ported it to my syntax, as I was
    curious how it would look. This is the result:

    https://github.com/bart-2026/langs/blob/main/lexertest.m

    (It's been spaced out more, vertically.)

    There were some tricky bits of the C to translate, such as:

    break;
    default:
    break;
    }
    default:
    *tp++ = ch;
    break;
    }
    }
    *tp++ = '\0';
    tt = TkSTRING;

    where it seems to break from one switch then sneakily falls through
    into the default clauses of the enclosing one!

    Yup.

    Well, here are some stats:

    C Mine

    Size 3374 2997 characters (both with hard
    tabs) Non-blank lines 210 174 Lines

    Those seem like pretty meaningless statistics. I could really
    care less about 377 fewer bytes. Naturally, different languages
    will express these things differently.

    I did try and run mine:

    c:\mapps>test
    1234
    tok: tt = tkident, token = '1234'
    abc
    tok: tt = tkident, token = 'abc'

    It shows both of these as an identifier. But yours does the same:

    c:\c>a
    1234
    tok: tt = 1003, token = '1234'
    abc
    tok: tt = 1003, token = 'abc'

    Yup. It's a poorly written program; I am not surprised there
    are bugs. It wasn't meant to be an illustration of exemplary
    programming, it was meant to illustrate a use case for a
    language construct that addresses a use case you appeared to
    want support for, but that are now upset about, because it was
    not provided in the way you like. Or something.

    Whatever '1003' means, it's showing the same. So it will do (I don't
    care if the code is buggy, just whether my version is reasonably
    faithful).

    This is actually a good example of the problem you often run
    into in these endless c.l.c threads: You seem to take a thing
    that was something that was only meant to show one thing, and
    asserting that it represents something other than what it was
    meant to show, and no matter how many times it is explained to
    you that it is not, in fact, what you seem to think that it is,
    you persist in your delusion and think that it proves something.
    But it doesn't, since you are starting from a false premise, at
    which point you whine that you are picked on, treated poorly,
    misunderstood, or generally dismissed, to which you conclude
    that this can only be due to a slavish devotion to C as it is,
    and a refusal to entertain that the language is not perfect. It
    is totally lost on you that people may be objecting to what you
    are saying on its own merits, since (ironically) you don't seem
    able to admit that your own ideas may have their own
    deficiencies.

    This whole discussion could be summarized as:

    Bart: "C sucks because Dennis Ritchie stupidly reused `break`
    for both loops and switch. He was a tasteless fool."
    All: "You can work around that really easily."
    Keith: "C added labeled break and continue...."
    Bart: "C sucks. My language is better. Here, I fixed C in 4
    lines of code with my `breakloop`, but it still sucks
    because C is hopeless."
    Me: "No, the real problem is that there's no structured way
    break out of nested contexts; your thing only addresses
    one special case, and does not compose, so can't cover
    the general case."
    Bart: "No, it's the overloading. C is terrible and you're all
    just too blind to see it. You are all fools, like
    Dennis Ritchie."
    Me: "I mean, Keith told you how the language is being changed
    to address your problem _and_ the other problems in this
    general category."
    Bart: "Those other problems don't matter. C will never change.
    It will suck forever. I mean, have you ever even seen a
    use case for these labeled blocks? I don't like them,
    therefore they suck, just like C. They also suck
    because they solve a problem I don't care about. I have
    been doing this for 45 years."
    Me: "Here's a program that illustrates the problem. The code
    is shit, but shows how it can be used...."
    Bart: "This program sucks! You don't _need_ to do it this
    way."
    Me: "...I mean, I told you it sucked when I posted it...."
    Bart: "...I rewrote it in my language. I saved 377 bytes. See
    how much C sucks now? My language is better.
    Me: "...."
    Bart: "My lexer is 50% faster than your lexer. My production
    code is an order of magnitude faster. I am a very smart
    boy, and deserve a very special gold star on my report
    card."
    Me: "...Bruh."
    Bart: "Dennis Ritchie was a fool. A fool, I say! Haha!
    Ahahaha! Muwhahaha!"


    So, you don't like Donald Trump. Most people that read comp.os.vms
    already knew it.
    But why do you make bart responsible for that?


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Thu Oct 15 23:22:04 2026
    From Newsgroup: comp.lang.c

    On 15/10/2026 21:42, Dan Cross wrote:
    In article <11aqpl3$2gdup$[email protected]>, bart <[email protected]> wrote:

    Those seem like pretty meaningless statistics.
    Naturally, different languages will express these things differently.

    My syntax has cleaner and simpler syntax compared to C, and handles
    features like 'switch' more ergonomically. In this case, C had a 20%
    higher line count - fact.

    But it seems people don't value cleaner, more productive syntax when it
    it comes to 'serious' languages, only scripting ones. OK; your loss.

    This whole discussion could be summarized as:

    Bart: "C sucks because Dennis Ritchie stupidly reused `break`
    for both loops and switch. He was a tasteless fool."
    All: "You can work around that really easily."
    Keith: "C added labeled break and continue...."
    Bart: "C sucks. My language is better. Here, I fixed C in 4
    lines of code with my `breakloop`, but it still sucks
    because C is hopeless."
    Me: "No, the real problem is that there's no structured way
    break out of nested contexts; your thing only addresses
    one special case, and does not compose, so can't cover
    the general case."
    Bart: "No, it's the overloading. C is terrible and you're all
    just too blind to see it. You are all fools, like
    Dennis Ritchie."
    Me: "I mean, Keith told you how the language is being changed
    to address your problem _and_ the other problems in this
    general category."
    Bart: "Those other problems don't matter. C will never change.
    It will suck forever. I mean, have you ever even seen a
    use case for these labeled blocks? I don't like them,
    therefore they suck, just like C. They also suck
    because they solve a problem I don't care about. I have
    been doing this for 45 years."
    Me: "Here's a program that illustrates the problem. The code
    is shit, but shows how it can be used...."
    Bart: "This program sucks! You don't _need_ to do it this
    way."
    Me: "...I mean, I told you it sucked when I posted it...."
    Bart: "...I rewrote it in my language. I saved 377 bytes. See
    how much C sucks now? My language is better.
    Me: "...."
    Bart: "My lexer is 50% faster than your lexer. My production
    code is an order of magnitude faster. I am a very smart
    boy, and deserve a very special gold star on my report
    card."
    Me: "...Bruh."



    You know, I could well be right about all those points. Maybe my
    language that has been around for 45 years really is a sweeter, cleaner
    'C' which has solved most of the latter's quirks.

    And maybe other people's responses to that is just sour grapes.

    However one of interests is PL design - specifically at this level - and
    how C gets it so wrong, how people defend it so much, how it evolves so glacially, how much fixing its shortcomings is offloaded to tools, is fascinating.

    It would have been nice to have a more objective discussion about such aspects, with people not afraid to be a LOT more critical of C and its
    tools that they have been.

    But I guess this is the wrong forum for that.



    Bart: "Dennis Ritchie was a fool. A fool, I say! Haha!>
    Ahahaha! Muwhahaha!"

    Simplest kind of function pointer:

    Bart: ref proc
    DMR: void(*)(void)

    Simplest function pointer variable:

    Bart: ref proc abc
    DMR: void(*abc)(void);

    Two such variables:

    Bart: ref proc one, two
    DMR void (*one)(void), (*two)void; // I think

    Two variables each an array 10 of such pointers:

    Bart: [10]ref proc one, two
    DMR: No fucking clue mate...

    (Apparently it would be this, according to a tool which transpiles to C:

    void (*one[10])(void), (*two[10])(void);

    Fucking hell. Actually I didn't call DMR a fool. I did mention a
    'numskull' which I now withdraw; I prefer to criticise ideas not people.
    But this is a disaster.)


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Fri Oct 16 02:42:53 2026
    From Newsgroup: comp.lang.c

    On 15/10/2026 18:10, bart wrote:
    On 15/10/2026 15:57, bart wrote:
    On 15/10/2026 12:45, Dan Cross wrote:
    In article <11aqbqv$2avn3$[email protected]>, bart  <[email protected]> wrote: >>
    Perhaps that reused keyword thing is a bigger deal than you think. The >>>> effect of it is unnecessary obfuscation.

    This is certainly not evidence of that.  This is just your
    assertion that you took a silly example and apparently (maybe?)
    improved it, based on some unstated, but apparently subjective,
    criteria.
    I am stating that 'break' used to fix C's poor 'switch' feature
    interferes with 'break' used for loops.

    It's not even my opinion: it's fact. In your example, about a third of
    'break' tokens are for taking care of switch.

    My opinion is that it generates pointless clutter (this it would do
    even if a different keyword was used), and it can get confusing when
    switch and loop are mixed up.

    I actually took your program and ported it to my syntax, as I was
    curious how it would look. This is the result:

    https://github.com/bart-2026/langs/blob/main/lexertest.m

    (It's been spaced out more, vertically.)

    Well, here are some stats:

    I did try and run mine:
    Enough worked that I decided to try a speed test. Both use exactly the
    same algorithm, and I didn't expect either to be fast.

    Still, the version in my language/compiler was 50% faster than the C compiled with gcc-O3. I don't know why.
    I'm mildly curious about this even if no one else is (or they think it
    is some sort of boasting although I said I didn't know the reason).

    I've now converted DC's C program to use normal gotos, so that I can try
    with other compilers.

    For my test (10M lines of the same 8 tokens):

    gcc 16.x 28 seconds (any opt. level)
    gcc 14.x 18 seconds
    clang-O3 18 seconds
    tcc 18 seconds
    bcc 18 seconds
    mm 18 seconds (my lang)

    Figures are pretty much at those two levels.

    So it's more likely a library thing and it is i/o bound.

    Anyway, I'm done with all this now; my C compiler and related apps are
    no more.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Tim Rentsch@[email protected] to comp.lang.c on Fri Oct 16 03:36:31 2026
    From Newsgroup: comp.lang.c

    Andrey Tarasevich <[email protected]> writes:

    On Sun 10/11/2026 6:33 AM, David Brown wrote:

    It is quite obvious that it is easy to write code with loops + break
    within a switch. It is equally obvious that it is easy to avoid
    such constructs - there are always ways to avoid a "break" in a
    loop, and if the code run within a switch case is complex, it is
    often practical to refactor it into a separate function. But
    presumably Michael has reasons not do do that.

    Um... The common pattern for a "search"-style loop looks as follows

    for (/* domain condition */)
    {
    ...
    if (/* search condition */)
    break;
    ...
    }

    So, loops that terminate with `break` are the mainstay of every
    competently written code. Moving the "early termination" condition
    into the loop header (i.e. lumping the search condition with the
    domain condition) is a very ugly anti-pattern in most cases. Moreover, majority of the loops in an average C program are such "search"-style
    loops, meaning that they do have an "early termination" condition.

    Now, while overwhelming majority of my loops would use `if` to check
    the "early termination", I can imagine that there sill be cases where
    switch` is applicable and more appropriate than an `if`. Yes, a
    switch` can always be replaced with an `if` ladder, but being _forced_
    to do so by a language limitation doesn't look right.

    And writing a separate function just to work around a weird language limitation... that doesn't look right either.

    I'm afraid I must simply flat out disagree with some of the comments
    above.

    Certainly it is true that many C programs use a for-if-break pattern
    in some or many places. It's fair to call it a common pattern. But
    it's wrong to say it is /the/ common pattern. There are other ways
    of skinning that cat, and I expect most C programmers have used some
    or all of them in the normal course of program development.

    Similarly, the assertion that "loops that terminate with `break` are
    the mainstay of every competently written code" is an absurd
    overstatement. No doubt break-exiting loops are a significant part
    of many programs. Probably they are a mainstay in some of them.
    But to say they are /the/ mainstay in any non-trivial program is at
    best a stretch; to assert that they are /the/ mainstay in /all/
    competently written code is simply wrong.

    I looked at some statistics for a couple of code bases. The relative
    amounts of switch() versus loops (for(), while(), do/while()) was
    relatively constant, about one in six or one in seven. Use of break
    varied a lot, from close to six percent to under two percents (here
    percent means percentage of occurrences of all control keywords).
    The biggest category was if() and return, over 80% of the total and
    roughly eight times the amount of looping structures. In the scheme
    of things switch() is not very important. Loops are important. The
    more prominent if() and return are very important. The idea that,
    one, exiting a loop with break is always an essential program element
    and, two, it's important to be able to do that using switch(), isn't
    a good fit for the facts on the ground.

    Incidentally, the comment that writing a separate function "doesn't
    look right" seems backwards. Breaking large functions into smaller
    functions is a good way to make code easier to understand. By their
    nature switch() statements tend to be large (in terms of lines of
    code) so putting the switch() inside a separate function is likely to
    be a good thing, not a bad thing. The motivation for doing that is
    not about working around a language limitation, but about writing
    better code.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Tim Rentsch@[email protected] to comp.lang.c on Fri Oct 16 04:46:03 2026
    From Newsgroup: comp.lang.c

    Keith Thompson <[email protected]> writes:

    [.. some syntanx changes were made as part of C23 ..]

    C23 made some changes with the goal of allowing a label to be
    immediately followed by a declaration or `}`. It did so by changing
    the grammar for a compound-statement:

    compound-statement:
    { block-item-list[opt] }

    block-item-list:
    block-item
    block-item-list block-item

    block-item:
    declaration
    unlabeled-statement
    label

    This means that in

    switch (x) {
    case 'A':
    case 'B':
    case 'C':
    puts("blah");
    }

    *there is no labeled-statement*. Instead, each of `case 'A':`,
    `case 'B':`, `case 'C':`, and `puts("blah");` is a block-item, and all
    the block-items are at the same syntactic level within the compound-statement. (The indentation is still appropriate IMHO.)

    Since control jumps to "the statement or declaration following the
    matched case label", there is no fallthrough. If x == 'A', control
    jumps directly to the puts() call.

    In C17 and earlier, the same wording implies that when x=='A', control
    jumps to the statement
    case 'B': case 'C': puts("blah");
    so one might arguably refer to that as "fallthrough". In C23,
    case 'B': case 'C': puts("blah");
    is not a statement.

    A weird but mostly harmless consequence of this is that C23 keeps
    the syntactic construct of a *labeled-statement*, but it's used
    extremely rarely. Any C17-or-earlier labeled-statement at the
    top level of an enclosing compound-statement is no longer a C23 labeled-statement, even though it looks like one. In C23, a labeled-statement can only occur in an odd construct like this:

    if (condition)
    LABEL: statement;

    The proposal that led to this suggested an optional additional change,
    making labels outside of compound statements an obsolescent feature.
    That part of the proposal was not adopted.

    Glad to hear it. Good choice.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@[email protected] (Dan Cross) to comp.lang.c on Fri Oct 16 12:40:18 2026
    From Newsgroup: comp.lang.c

    In article <11arjmc$2qid7$[email protected]>, bart <[email protected]> wrote:
    ...
    My syntax has cleaner and simpler syntax compared to C,...

    I'm sure you meant to say, "my language has...".

    But it seems people don't value cleaner, more productive syntax when it
    it comes to 'serious' languages, only scripting ones....

    [snip]
    You know, I could well be right about all those points. Maybe my
    language that has been around for 45 years really is a sweeter, cleaner
    'C' which has solved most of the latter's quirks.

    And maybe other people's responses to that is just sour grapes.

    However one of interests is PL design - specifically at this level - and
    how C gets it so wrong, how people defend it so much, how it evolves so >glacially, how much fixing its shortcomings is offloaded to tools, is >fascinating.

    It would have been nice to have a more objective discussion about such >aspects, with people not afraid to be a LOT more critical of C and its
    tools that they have been.

    But I guess this is the wrong forum for that.

    I think objective discussions of C are appropriate for
    comp.lang.c. Your description is not objective. For example,
    you claim that "people don't value cleaner, more productive
    syntax...". But those are subjective criteria. Has it truly
    never occurred to you that many other people just don't consider
    your syntax significantly cleaner, or more productive?

    I'm sure your language is very nice. I recall looking at it at
    one point and thinking it was fine, though I saw nothing
    particularly special about it that would motivate me to want to
    give up the considerable network advantages of using a more
    common language.

    You really think that's just sour grapes? That everyone else is
    just, what...mad at you because they feel the need to defend C's
    honor or something? C isn't a member of my family. You're not
    insulting my ancestry by pointing out flaws in it. I'm not
    going to get personally upset about its imperfections.

    Perhaps people dismiss what you say because, despite your
    self-aggrandizing words, you've shown that you don't actually
    know C very well, and that you either do not care about, or
    misunderstand, basic aspects of the language. By your own
    admission you ignore in the standards documents. It is hard to
    take the criticism of someone who doesn't understand what they
    are criticizing very seriously, and subjectivity aside, relative
    statements about the superiority of your language with respect
    to a language you yourself don't know very well are similarly
    difficult to take seriously.

    Bart: "Dennis Ritchie was a fool. A fool, I say! Haha!>
    Ahahaha! Muwhahaha!"

    Simplest kind of function pointer:

    [snip; don't care]

    (Apparently it would be this, according to a tool which transpiles to C:

    void (*one[10])(void), (*two[10])(void);

    Yes, that's right.

    Fucking hell. Actually I didn't call DMR a fool. I did mention a
    'numskull' which I now withdraw; I prefer to criticise ideas not people.
    But this is a disaster.)

    For someone who claims to want to discuss C objectively, you
    sure do make a lot of subjective statements.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From antispam@[email protected] (Waldek Hebisch) to comp.lang.c on Fri Oct 16 15:24:01 2026
    From Newsgroup: comp.lang.c

    Lawrence D’Oliveiro <[email protected]d> wrote:
    On Tue, 13 Oct 2026 07:23:40 -0000 (UTC), Waldek Hebisch wrote:

    So what those counts indicate: majority of loops is simple, that is
    have no early exit. Vast majority of early exits is done via
    'return'.

    My experience in my own C code is quite the opposite. Lots of loops
    have exits in the middle, leading me to use forms like “for (;;)”. I
    also try to avoid putting “return” anywhere other than the end of a function, to make it easier to see the flow of control.

    Well, usually there is a lot of loops. Those with exit in the
    middle are still significant.

    Concernig 'return', having it in place where all work inside function
    is done help me to see flow control and avoids complications. In
    case of search functions it means return from the middle of the loop.
    IMO possible alternatives like flag variables or break and retrun
    after loop are worse.
    --
    Waldek Hebisch
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Tim Rentsch@[email protected] to comp.lang.c on Fri Oct 16 13:12:59 2026
    From Newsgroup: comp.lang.c

    Keith Thompson <[email protected]> writes:

    Janis Papanagnou <[email protected]> writes:

    On 2026-10-06 03:05, Keith Thompson wrote:

    [...]
    A weird but mostly harmless consequence of this is that C23 keeps
    the syntactic construct of a *labeled-statement*, but it's used
    extremely rarely. Any C17-or-earlier labeled-statement at the
    top level of an enclosing compound-statement is no longer a C23
    labeled-statement, even though it looks like one. In C23, a
    labeled-statement can only occur in an odd construct like this:
    if (condition)
    LABEL: statement;

    You've been arguing on the implicit difference in the language
    definition here. That's all a fine explanation.

    What I wonder about is what you find "odd" with that construct.
    For folks who use jumps and labels (not me) that looks not too
    odd to me; I can imagine programming cases where that may be
    useful.

    It's unlikely that I'd write something like that. If I did,
    I'd use braces:

    if (condition) {
    LABEL: statement;
    }

    I'm sometimes willing to omit optional braces, but almost exclusively
    in cases where the entire construct is on one line:

    if (condition) statement;

    Some years ago I had occasion to write some code that in outline
    looked something like this (pseudo code in <>'s):

    <typename>
    some_action( <arguments> ){

    <some setup>

    goto START_LOOP;
    for( ; <test>; <update> ){
    if( <early-exit-test> ) return <something>;
    if( <circumstance> ) START_LOOP: {
    <re-initialization actions>
    }
    }

    <rest of function>
    }

    I deliberately put the label START_LOOP before the braces because I
    wanted to make it obvious that the target was the whole branch of
    the if(). Putting the label inside the braces could give the
    mistaken impression that it was just a coincidence that what happens
    when the loop starts is the entire body of the if(). Putting the
    label before the braces makes it obvious that what the if() is doing
    and where the loop is being entered are exactly the same point.

    Aside from that, writing an if statement and providing a way to bypass
    the test feels odd (to me). Presumably there's a `goto LABEL;`
    elsewere in the same function. I'd look for a clearer way to structure
    the code.

    Indeed, and not only did I look, but I already had looked, and ended
    up at the above version only after trying multiple alternatives. I
    judged this variation to be the easiest to understand, because all
    the alternatives either were more convoluted or had to duplicate
    some code, not only the code in the if() body but also the <update>
    clause in the for() statement.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Tim Rentsch@[email protected] to comp.lang.c on Fri Oct 16 14:22:46 2026
    From Newsgroup: comp.lang.c

    Keith Thompson <[email protected]> writes:

    I find "break NAME;", where "NAME" is the name of an enclosing
    construct, unambiguously better than "break N;", where N is the
    number of levels to break out of. [...]

    Definitely.

    There's a proposal for C2y to use goto labels as loop names, and a
    competing one to define a new syntax like "for NAME (;;)" :

    https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3355.htm https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3377.pdf

    I'm not particularly a fan of multi-level break/continue. But if
    we're going to have one of these, the second ("for NAME (;;)") is unquestionably better.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@[email protected] to comp.lang.c on Fri Oct 16 21:42:35 2026
    From Newsgroup: comp.lang.c

    On Fri, 16 Oct 2026 15:24:01 -0000 (UTC), Waldek Hebisch wrote:

    Concernig 'return', having it in place where all work inside
    function is done help me to see flow control and avoids
    complications. In case of search functions it means return from the
    middle of the loop. IMO possible alternatives like flag variables or
    break and retrun after loop are worse.

    Code tends to do a lot of dynamic resource allocation these days, and
    that requires cleanup. Doing a direct “return” from the middle of a function body doesn’t allow for that.

    Unless you use a GCC extension like “defer”, I suppose.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From scott@[email protected] (Scott Lurndal) to comp.lang.c on Fri Oct 16 21:46:22 2026
    From Newsgroup: comp.lang.c

    Lawrence =?iso-8859-13?q?D=FFOliveiro?= <[email protected]d> writes:
    On Fri, 16 Oct 2026 15:24:01 -0000 (UTC), Waldek Hebisch wrote:

    Concernig 'return', having it in place where all work inside
    function is done help me to see flow control and avoids
    complications. In case of search functions it means return from the
    middle of the loop. IMO possible alternatives like flag variables or
    break and retrun after loop are worse.

    Code tends to do a lot of dynamic resource allocation these days, and
    that requires cleanup. Doing a direct “return” from the middle of a >function body doesn’t allow for that.

    Unless you use a GCC extension like “defer”, I suppose.

    Better to use the cleanup attribute (or RAII in C++).

    #define RAII_CHM __attribute__((cleanup(auto_free_ptr)))
    #define RAII_FILE __attribute__((cleanup(auto_close_file)))

    int main(void) {
    // Memory and file handles are bound to this block scope
    RAII_CHM char *buffer = malloc(100);
    RAII_FILE FILE *fp = fopen("example.txt", "w");

    if (!buffer || !fp) {
    return -1; // Even on early exit, validly opened resources are cleaned up!
    }

    fprintf(fp, "Hello, RAII in C!");

    return 0; // Both buffer and fp are automatically freed/closed here
    }
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@[email protected] to comp.lang.c on Fri Oct 16 15:00:27 2026
    From Newsgroup: comp.lang.c

    Tim Rentsch <[email protected]> writes:
    Keith Thompson <[email protected]> writes:
    I find "break NAME;", where "NAME" is the name of an enclosing
    construct, unambiguously better than "break N;", where N is the
    number of levels to break out of. [...]

    Definitely.

    There's a proposal for C2y to use goto labels as loop names, and a
    competing one to define a new syntax like "for NAME (;;)" :

    https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3355.htm
    https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3377.pdf

    I'm not particularly a fan of multi-level break/continue. But if
    we're going to have one of these, the second ("for NAME (;;)") is unquestionably better.

    Unquestionably? Why?

    I do like the fact that it doesn't conflate goto labels with loop
    names, but I still prefer the "NAME: for (;;)" form, partly because
    it's consistent with several other languages.

    One minor drawback, IMHO, is that the name is easier to miss, because
    it's not at the beginning of the line. This is based on zero experience
    using it.

    (The same problem exists with function names. Personally, I just
    tolerate that rather than using the common convention of splitting the
    return type and function name across two lines. I think I would have
    preferred a syntax that puts the function name first, but I wouldn't
    suggest changing it. I mildly dislike the convention of writing
    int
    func(void)
    for reasons that are vague enough that I won't go into them.)
    --
    Keith Thompson (The_Other_Keith) [email protected]
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@[email protected] to comp.lang.c on Fri Oct 16 15:03:19 2026
    From Newsgroup: comp.lang.c

    Lawrence D’Oliveiro <[email protected]d> writes:
    [...]
    Unless you use a GCC extension like “defer”, I suppose.

    There is a proposal to add "defer" (or rather "_Defer") to C,
    though it doesn't appear in the latest C2y draft.

    https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3928.pdf
    --
    Keith Thompson (The_Other_Keith) [email protected]
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Sat Oct 17 00:01:52 2026
    From Newsgroup: comp.lang.c

    On 16/10/2026 13:40, Dan Cross wrote:
    In article <11arjmc$2qid7$[email protected]>, bart <[email protected]> wrote:

    Has it truly
    never occurred to you that many other people just don't consider
    your syntax significantly cleaner, or more productive?
    So why is this style of syntax popular within scripting languages? (Lua, Julia, Ruby...)

    Those are considered more productive.

    Perhaps people dismiss what you say because, despite your
    self-aggrandizing words, you've shown that you don't actually
    know C very well,

    See the type syntax example below. How well do you need to know a
    language to see that that is just effing crazy? This is supposed to be a
    HLL, not a puzzle that needs to be solved or decoded via algorithms or employing tools!

    For someone who claims to want to discuss C objectively, you
    sure do make a lot of subjective statements.

    Concerning type declaration syntax, lots of people including the C
    creators agree that it was misguided.

    If lots of people agree, is that still being subjective? This is the
    example I think used in K&R:

    char *(*(**foo [][8])())[];

    Most would consider this gobbledygook even if you know the rules. It is atrocious syntax. And what's 'foo' doing in the middle of it!

    I think being defensive about it is being subjective, as you demonstrate
    here:

    [snip; don't care]

    That is pretty much the attitude here in a nutshell.

    What's often stated also is how successful C has been, but that doesn't magically make the syntax wonderful.

    If DMR had instead produced a language that looked like mine (say like
    one of the Algols), and I came along in 2026 and proposed a syntax that
    looked like the above, what do you think the response would be?

    I would rightly be laughed out of the forum.

    So being 'objective' means disregarding history and widespread adoption.
    The latter doesn't make the language better, just more tolerated, with
    more effort put into tools to make it practical to use (with a nice
    sideline in teaching all its ins and outs).

    Anyway, to me, pretty much the whole of C looked as badly and crudely
    put together as that, when I first came across it in 1982. My background
    had been with quite different languages.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@[email protected] to comp.lang.c on Sat Oct 17 01:29:32 2026
    From Newsgroup: comp.lang.c

    On 2026-10-17 00:00, Keith Thompson wrote:
    Tim Rentsch <[email protected]> writes:
    Keith Thompson <[email protected]> writes:
    [...]
    There's a proposal for C2y to use goto labels as loop names, and a
    competing one to define a new syntax like "for NAME (;;)" :
    [...]

    I'm not particularly a fan of multi-level break/continue. But if
    we're going to have one of these, the second ("for NAME (;;)") is
    unquestionably better.

    Unquestionably? Why?

    Why would one question an opinion? ;-)


    I do like the fact that it doesn't conflate goto labels with loop
    names, but I still prefer the "NAME: for (;;)" form, partly because
    it's consistent with several other languages.

    I've no strong opinion on that, but I find the "for NAME (;;)" to
    clearer express the _local scope_ of embedded breaks or continues.
    (Just a matter of taste, and my appreciation for locality.)


    One minor drawback, IMHO, is that the name is easier to miss, because
    it's not at the beginning of the line. This is based on zero experience using it.

    If that sort of jump would be _restricted_ to the respective loop
    then I'd not see how I'd miss that since it's closely placed. (It
    might also help if, as shown above, some all-caps convention would
    be applied to labels.)


    (The same problem exists with function names. Personally, I just
    tolerate that rather than using the common convention of splitting the
    return type and function name across two lines. I think I would have preferred a syntax that puts the function name first, but I wouldn't
    suggest changing it. I mildly dislike the convention of writing
    int
    func(void)
    for reasons that are vague enough that I won't go into them.)

    Well, there were both variants, the Algol 60 "integer procedure"
    and the Algol 68 "(...) INT :" (or Pascal's syntax equivalent with
    a 'function' keyword, similarly, but with another syntax, in Awk).
    But there's more syntactic factors that influence where the name is
    located, so many variants are existing. (But we're anyway talking
    just about "C", so it's all void, whatever personal preferences.)

    The point with the separation of two lines is a question distinct
    from the choice, unless we'd choose a syntactic variant of the two
    forms, specifically "fname (parms) res_t" (i.e. without keyword).

    As far as I recall, in "C", the name of the function was often put
    separately (first in the line) to have an easy method to find its
    declaration by simple "grep ^fname". (With any sophisticated editor
    this might be a weak argument, though.)

    Janis

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@[email protected] to comp.lang.c on Fri Oct 16 16:53:18 2026
    From Newsgroup: comp.lang.c

    bart <[email protected]> writes:
    [...]
    What's often stated also is how successful C has been, but that
    doesn't magically make the syntax wonderful.

    NOBODY THINKS C'S SYNTAX IS WONDERFUL.

    We surrender. You win. Stop fighting.

    [...]
    --
    Keith Thompson (The_Other_Keith) [email protected]
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@[email protected] (Dan Cross) to comp.lang.c on Sat Oct 17 03:19:17 2026
    From Newsgroup: comp.lang.c

    In article <11auad0$3no1k$[email protected]>, bart <[email protected]> wrote:
    On 16/10/2026 13:40, Dan Cross wrote:
    In article <11arjmc$2qid7$[email protected]>, bart <[email protected]> wrote:

    Has it truly
    never occurred to you that many other people just don't consider
    your syntax significantly cleaner, or more productive?

    So why is this style of syntax popular within scripting languages? (Lua, >Julia, Ruby...)

    Those are considered more productive.

    ...and you think that's because of the syntax, and not the high
    level nature of those languages?

    Wow.

    Perhaps people dismiss what you say because, despite your
    self-aggrandizing words, you've shown that you don't actually
    know C very well,

    See the type syntax example below. How well do you need to know a
    language to see that that is just effing crazy? This is supposed to be a >HLL, not a puzzle that needs to be solved or decoded via algorithms or >employing tools!

    Yes, the syntax is pretty gnarly; Dennis Ritchie even said as
    much. Fixed in Go and Rust, but also, I doubt you've ever in
    your life had a variable of type array of array of length 8 of
    a pointer to a pointer to a function returning an array of
    pointers to char. Finding the most ridiculous example you can
    is not really evidence of anything besides your weird obsession
    with finding abstruse corner cases and holding them up as
    reasons to dislike C.

    For someone who claims to want to discuss C objectively, you
    sure do make a lot of subjective statements.

    Concerning type declaration syntax, lots of people including the C
    creators agree that it was misguided.

    Yup. But stupid examples are just stupid.

    If lots of people agree, is that still being subjective? This is the
    example I think used in K&R:

    char *(*(**foo [][8])())[];

    Most would consider this gobbledygook even if you know the rules. It is >atrocious syntax. And what's 'foo' doing in the middle of it!

    Yup. That's awful.

    I think being defensive about it is being subjective, as you demonstrate >here:

    [snip; don't care]

    I fail to see how me not caring about your silly examples is
    being defensive about C. It says nothing about what I think
    about C one way or the other; it only says I think your
    arguments are poorly grounded.

    That is pretty much the attitude here in a nutshell.

    What's often stated also is how successful C has been, but that doesn't >magically make the syntax wonderful.

    No one is claiming that C's popularity implies it's a "good"
    language, however you'd like to define that. There are useful
    properties that come with using it, including a large ecosystem
    of libraries and tools, huge number of programmers who know it,
    lots of high-quality references, and so on. But again, that
    doesn't mean that C is good, just that we can leverage it's
    popularity _usefully_.

    If DMR had instead produced a language that looked like mine (say like
    one of the Algols), and I came along in 2026 and proposed a syntax that >looked like the above, what do you think the response would be?

    But he didn't, and you didn't, so this is a meaningless
    historical, "what if?"

    I would rightly be laughed out of the forum.

    Bruh...I hate to break it to you, but....

    So being 'objective' means disregarding history and widespread adoption.

    Well, no...both of those are factors in choosing a language or
    not. We can discuss the semantics of the language, it's syntax,
    etc; but we can also discuss tooling, engineering resources
    availability (can you find programmers who know C? More like,
    can you find programmers who _don't_ know C, amirite?), library
    and platform support, and so on.

    The latter doesn't make the language better, just more tolerated, with
    more effort put into tools to make it practical to use (with a nice
    sideline in teaching all its ins and outs).

    This I can almost get behind, but you miss the forest for the
    trees. All those resources? They exist; we can leverage them.
    For BartLang? Not so much.

    Is C a good language? Meh, it's not the worst, but far from the
    best I've seen. Was it a bad language in 1972, when it was
    targeting a PDP-11/20? No, it was pretty decent for that era.
    Did it do all the stuff that fancy languages with advanced
    compilers that ran on big machines could do? No. Did it need
    to? Also no.

    Anyway, to me, pretty much the whole of C looked as badly and crudely
    put together as that, when I first came across it in 1982. My background
    had been with quite different languages.

    Yup. Good for you. So why do you keep posting here?

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From gazelle@[email protected] (Kenny McCormack) to comp.lang.c on Sat Oct 17 11:09:21 2026
    From Newsgroup: comp.lang.c

    In article <11audde$3oci5$[email protected]>,
    Keith Thompson <[email protected]> wrote:
    bart <[email protected]> writes:
    [...]
    What's often stated also is how successful C has been, but that
    doesn't magically make the syntax wonderful.

    NOBODY THINKS C'S SYNTAX IS WONDERFUL.

    The funny thing is: I actually do.

    I may be the only person here who actually thinks the syntax of C's
    "switch" statement is just fine. Once you realize that it *is* more of a computed goto rather than a high level alternation construct like you'd
    find in a real high level language (C is *not* a high level language; it is properly referred to as a "mid level" language).

    Note that the underlying issue here is easily dealt with if you do both of
    the following:
    a) Enable the warning in your compiler that warns about (unannotated)
    fallthrough.
    and
    b) Always put a comment when you intentionally do fallthrough.

    This issue is kind of similar to the old:

    if (a = b) ...

    thing - which really was a problem - right up until compilers started
    warning about it. Now that all compilers warn if you do that, it is no
    longer a live issue, but people still bring it up occasionally.

    FWIW, to take another popular whipping boy of C, I also actually like the variable declaration syntax - which many people like to criticize as "backwards" or "inside out". Once you get used to it, it makes perfect
    sense (to me, anyway). I have no problem with a declaration like:

    int i,j,*ip,arr[10],foo(int bar);

    Some would say that declares lots of different types of objects, but I
    think of them all as ints (which is what the declaration is telling us).
    --
    The randomly chosen signature file that would have appeared here is more than 4-ish
    lines long. As such, it violates one or more Usenet RFCs. In order to remain in compliance with said RFCs, the actual sig can be found at the following URL:
    http://user.xmission.com/~gazelle/Sigs/Seneca
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Sat Oct 17 12:34:02 2026
    From Newsgroup: comp.lang.c

    On 17/10/2026 04:19, Dan Cross wrote:
    In article <11auad0$3no1k$[email protected]>, bart <[email protected]> wrote:

    Those are considered more productive.

    ...and you think that's because of the syntax, and not the high
    level nature of those languages?

    It's a combination.

    Yes, the syntax is pretty gnarly; Dennis Ritchie even said as
    much. Fixed in Go and Rust, but also, I doubt you've ever in
    your life had a variable of type array of array of length 8 of
    a pointer to a pointer to a function returning an array of
    pointers to char. Finding the most ridiculous example you can
    is not really evidence of anything besides your weird obsession

    That was the first one I saw online next to a quote from K&R and I
    assumed it was from the book. In fact the example from the book is this:

    char (*(*x())[])()

    I've no idea what the means either. The point is not that the examples
    are ridiculous, but that they are hard to convert to and from LTR form
    which is how we think. With LTR syntax it becomes utterly trivial to
    read or write them, no matter how complex.

    (There's a tool called CDECL that translates types from C syntax to LTR English or vice versa. It calls the C versions 'gibberish'. This is a
    real thing!)


    with finding abstruse corner cases and holding them up as
    reasons to dislike C.

    The first example I gave was the simplest form of function pointer,
    where the syntax is 'void(*)(void)'. Hardly a corner case, and it
    rapidly goes downhill.

    If meeting C for the first time, that does not bode well. If the
    designers did not care about this, that does not inspire confidence in
    the rest of the language.

    If DMR had instead produced a language that looked like mine (say like
    one of the Algols), and I came along in 2026 and proposed a syntax that
    looked like the above, what do you think the response would be?

    But he didn't, and you didn't, so this is a meaningless
    historical, "what if?"

    You don't get the point. If C had used LTR type syntax and somebody
    proposed using inside-out back-and-forth syntax like 'void(*)(void)',
    they'd think they were having a laugh, as it would be ridiculous.

    But this is exactly what I think about it anyway, no matter that 100
    million programs have battled with it for 50 years.


    So being 'objective' means disregarding history and widespread adoption.

    Well, no...both of those are factors in choosing a language or
    not. We can discuss the semantics of the language, it's syntax,
    etc; but we can also discuss tooling, engineering resources
    availability (can you find programmers who know C? More like,
    can you find programmers who _don't_ know C, amirite?), library
    and platform support, and so on.

    Yes, this is my point; it is tolerated, and people learn to work with
    it. But how much extra effort has been expended, compared if they'd
    tried a bit harder to get a better language at the start? Or even during
    its first decade.

    Is C a good language? Meh, it's not the worst, but far from the
    best I've seen. Was it a bad language in 1972, when it was
    targeting a PDP-11/20? No, it was pretty decent for that era.

    Disagree.

    Did it do all the stuff that fancy languages with advanced
    compilers that ran on big machines could do? No. Did it need
    to? Also no.

    I think C was first created for PDP7 with 4K words, then moved to PDP11
    (don't know the spec).

    My first language was created nearly a decade later on a /homemade/ microprocessor system with 32KB, but no viable storage. So compiler
    binary and data, editor, program source code, binary and data all had to reside in memory at the same time.

    That crude language had 'print x' and loops that looked like 'for i:=a
    to b do'. It also had a 'byte' type (ie. u8).

    A year or two later, with 64KB and storage, it was more full-featured.
    It was a viable and practical alternative to C which I had looked at,
    and dismissed.

    Fun fact: my copy of K&R1 cost me £12. My first Z80 processor cost £10.

    My point is you can't excuse C being what it is due to hardware limitations.

    I used PDP11 quite a bit (/34) and that had a decent Fortran implementation.

    My own stuff was done in my spare time for no extra pay, on 8-bit
    machines I helped develop for my company, without the backing of Bell Labs.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Sat Oct 17 13:11:37 2026
    From Newsgroup: comp.lang.c

    On 17/10/2026 12:09, Kenny McCormack wrote:
    In article <11audde$3oci5$[email protected]>,
    Keith Thompson <[email protected]> wrote:
    bart <[email protected]> writes:
    [...]
    What's often stated also is how successful C has been, but that
    doesn't magically make the syntax wonderful.

    NOBODY THINKS C'S SYNTAX IS WONDERFUL.

    The funny thing is: I actually do.

    I may be the only person here who actually thinks the syntax of C's
    "switch" statement is just fine. Once you realize that it *is* more of a computed goto

    Then maybe the syntax for it should have been:

    goto (x) {}

    instead of:

    switch (x) {}

    That would not clash with 'goto label', nor the 'goto *(x)' of gnu C.

    It would make it clearer that this is a cruder construct than 'switch' pretends to be, AND it saves a keyword!

    That saving could have gone towards giving switch-break its own keyword instead of having to share 'break' with loops (because there was
    apparently a shortage of keywords in 1972).

    That was always going to clash at some point, and it does.

    sense (to me, anyway). I have no problem with a declaration like:

    int i,j,*ip,arr[10],foo(int bar);

    Some would say that declares lots of different types of objects, but I
    think of them all as ints (which is what the declaration is telling us).

    It's taking a bunch of unrelated types of arbitrary complexity, but
    because they all end with a type T when expressed in LTR form, they all
    belong together?

    That doesn't work: i, ip, arr, foo all have different types.

    They only have the same types when fully dereferenced, indexed or
    called, when written as i, *ip, arr[i], foo(i). This is NOT when happens within the declaration, and it might not happen when they appear in expressions either.

    It's just confusing.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@[email protected] to comp.lang.c on Sat Oct 17 15:15:53 2026
    From Newsgroup: comp.lang.c

    On 2026-10-17 13:09, Kenny McCormack wrote:
    In article <11audde$3oci5$[email protected]>,
    Keith Thompson <[email protected]> wrote:
    bart <[email protected]> writes:
    [...]
    What's often stated also is how successful C has been, but that
    doesn't magically make the syntax wonderful.

    NOBODY THINKS C'S SYNTAX IS WONDERFUL.

    The funny thing is: I actually do.

    Hah! - That's the touche when someone formulates generalizing
    statements about "all people" or about "nobody". :-)

    That said; I'd anyway never expected anyone to have chosen the
    attribute "wonderful", though (which was the word used here).

    But I also think that what Keith wanted to say was that "nobody
    has *said* - before your post - that C's syntax is wonderful"
    (in reply to bart's typical wrong imputations and hallucinations
    what others would have implied by some [unrelated] statement).

    ['switch' topic - snipped]
    ["if (a = b)" topic - snipped]

    FWIW, to take another popular whipping boy of C, I also actually like the variable declaration syntax -

    (I'm reading that as "declaration syntax", i.e. without "variable".)

    which many people like to criticize as
    "backwards" or "inside out". Once you get used to it, it makes perfect
    sense (to me, anyway). [...]

    But isn't that exactly the point, that you need to "get used"
    to something, which makes it appear as a "bad" design decision
    to others. (I certainly got used to many things in life, but
    some I then just try to avoid.)

    And of course "it makes sense"; if you can formally describe it -
    and programming language syntaxes have that property - it makes
    sense. Is it a "good" (or even a "wonderful") design? - I don't
    think so. YMMV.

    I like some of the programming-idioms that "C" made popular, but
    its syntax - and specifically that convoluted declaration syntax -
    is certainly not amongst them. (Or requiring 'typedef' workarounds
    to make some of the less-trivial declarations manageable and the
    code significantly better readable.)

    We can observe that if one spent a lot time in some context, and
    is used to it, and at some point even masters it, he might not be
    considering it as negative as someone who is more of a wanderer
    between worlds, for whom the advantages and disadvantages of the
    worlds might be more obvious. - And all those hypes...

    Oh! - I just noticed I'm digressing.

    Janis

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Tim Rentsch@[email protected] to comp.lang.c on Sat Oct 17 08:34:05 2026
    From Newsgroup: comp.lang.c

    Keith Thompson <[email protected]> writes:

    bart <[email protected]> writes:
    [...]

    What's often stated also is how successful C has been, but that
    doesn't magically make the syntax wonderful.

    NOBODY THINKS C'S SYNTAX IS WONDERFUL.

    We surrender. You win. Stop fighting.

    If you would stop trying to engage with bart you wouldn't
    get so frustrated. And everyone would be happier. (It
    would be even nicer if other people would follow this
    advice too... hint hint hint).

    Incidentally I don't think C's declaration is wonderful,
    but I don't mind it either.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Michael S@[email protected] to comp.lang.c on Sat Oct 17 19:39:08 2026
    From Newsgroup: comp.lang.c

    On Fri, 16 Oct 2026 15:00:27 -0700
    Keith Thompson <[email protected]> wrote:

    Tim Rentsch <[email protected]> writes:
    Keith Thompson <[email protected]> writes:
    I find "break NAME;", where "NAME" is the name of an enclosing
    construct, unambiguously better than "break N;", where N is the
    number of levels to break out of. [...]

    Definitely.

    There's a proposal for C2y to use goto labels as loop names, and a
    competing one to define a new syntax like "for NAME (;;)" :

    https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3355.htm
    https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3377.pdf

    I'm not particularly a fan of multi-level break/continue. But if
    we're going to have one of these, the second ("for NAME (;;)") is unquestionably better.

    Unquestionably? Why?


    I don't know why Tim prefers it.
    I prefer it (strongly) because it is different from regular label. So
    reader that wants to understand a flow of the program should not be
    concerned with possibility of jumping to it from places outside for().

    I do like the fact that it doesn't conflate goto labels with loop
    names, but I still prefer the "NAME: for (;;)" form, partly because
    it's consistent with several other languages.


    You mentioned itself that in Ada loop labels are distinct from regular
    labels. I would think that Ada alone easily outweighs "several other
    languages" if we compare by number (and likely by quality) of man-hours invested into thinking and discussion of syntactic features.
    Anyway I value appeal to success more than appeal to authority so by my
    own standards the argument above is weak.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Sat Oct 17 18:23:47 2026
    From Newsgroup: comp.lang.c

    On 17/10/2026 17:39, Michael S wrote:
    On Fri, 16 Oct 2026 15:00:27 -0700
    Keith Thompson <[email protected]> wrote:

    Tim Rentsch <[email protected]> writes:
    Keith Thompson <[email protected]> writes:
    I find "break NAME;", where "NAME" is the name of an enclosing
    construct, unambiguously better than "break N;", where N is the
    number of levels to break out of. [...]

    Definitely.

    There's a proposal for C2y to use goto labels as loop names, and a
    competing one to define a new syntax like "for NAME (;;)" :

    https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3355.htm
    https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3377.pdf

    I'm not particularly a fan of multi-level break/continue. But if
    we're going to have one of these, the second ("for NAME (;;)") is
    unquestionably better.

    Unquestionably? Why?


    I don't know why Tim prefers it.
    I prefer it (strongly) because it is different from regular label. So
    reader that wants to understand a flow of the program should not be
    concerned with possibility of jumping to it from places outside for().

    I do like the fact that it doesn't conflate goto labels with loop
    names, but I still prefer the "NAME: for (;;)" form, partly because
    it's consistent with several other languages.


    You mentioned itself that in Ada loop labels are distinct from regular labels. I would think that Ada alone easily outweighs "several other languages" if we compare by number (and likely by quality) of man-hours invested into thinking and discussion of syntactic features.
    Anyway I value appeal to success more than appeal to authority so by my
    own standards the argument above is weak.

    I was around when Ada was being developed and refined, a process that
    took years.

    By contrast, C looks like it was just thrown together with little
    thought, and probably that is exactly what happened.

    In the end, Ada was a language that you could admire, but you'd rather
    other people used. It's a solid language but I found it too formal and
    rather dull (not that it was available for me to use).

    Still, I borrowed some syntactic features from it.

    One interesting fact that people might forget is that it was
    case-insensitive, a welcome difference IMV.




    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Tim Rentsch@[email protected] to comp.lang.c on Sat Oct 17 10:30:31 2026
    From Newsgroup: comp.lang.c

    Keith Thompson <[email protected]> writes:

    Tim Rentsch <[email protected]> writes:

    Keith Thompson <[email protected]> writes:

    I find "break NAME;", where "NAME" is the name of an enclosing
    construct, unambiguously better than "break N;", where N is the
    number of levels to break out of. [...]

    Definitely.

    There's a proposal for C2y to use goto labels as loop names, and a
    competing one to define a new syntax like "for NAME (;;)" :

    https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3355.htm
    https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3377.pdf

    I'm not particularly a fan of multi-level break/continue. But if
    we're going to have one of these, the second ("for NAME (;;)") is
    unquestionably better.

    Unquestionably? Why?

    Before I respond I'd like to ask you to list as many potential
    differentiators as you can think of, without regard to which of
    the two suggestions each one benefits, and without saying which
    ones you think favor one choice or the other. If you do that I
    can try to go through your list, say which ones I think are
    significant, which of the two choices each one favors, and maybe
    also assign some sort of priority ranking. Also that would give
    me a chance to think about whether there are other differentiators
    not on your list but that could seem to me to be relevant.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@[email protected] (Dan Cross) to comp.lang.c on Sat Oct 17 17:36:40 2026
    From Newsgroup: comp.lang.c

    In article <11b0av3$edsd$[email protected]>, bart <[email protected]> wrote:
    [snip]
    I was around when Ada was being developed and refined, a process that
    took years.

    By contrast, C looks like it was just thrown together with little
    thought, and probably that is exactly what happened.
    [snip]

    Oh put a sock in it, guy.

    No one here slavishly worships C or thinks it is perfect, but
    taking every little chance you can to throw barbs at it with
    otherwise utterly information-free posts like this, is merely
    noise. Honestly, the constant "notice me, senpai!" posts are
    just pathetic attention-seeking.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@[email protected] to comp.lang.c on Sat Oct 17 10:54:20 2026
    From Newsgroup: comp.lang.c

    Tim Rentsch <[email protected]> writes:
    Keith Thompson <[email protected]> writes:
    Tim Rentsch <[email protected]> writes:
    Keith Thompson <[email protected]> writes:
    I find "break NAME;", where "NAME" is the name of an enclosing
    construct, unambiguously better than "break N;", where N is the
    number of levels to break out of. [...]

    Definitely.

    There's a proposal for C2y to use goto labels as loop names, and a
    competing one to define a new syntax like "for NAME (;;)" :

    https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3355.htm
    https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3377.pdf

    I'm not particularly a fan of multi-level break/continue. But if
    we're going to have one of these, the second ("for NAME (;;)") is
    unquestionably better.

    Unquestionably? Why?

    Before I respond I'd like to ask you to list as many potential differentiators as you can think of, without regard to which of
    the two suggestions each one benefits, and without saying which
    ones you think favor one choice or the other. If you do that I
    can try to go through your list, say which ones I think are
    significant, which of the two choices each one favors, and maybe
    also assign some sort of priority ranking. Also that would give
    me a chance to think about whether there are other differentiators
    not on your list but that could seem to me to be relevant.

    No, Tim, I absolutely will not do that.

    I asked you to explain two words that you wrote. You do not get to
    assign me homework as a precondition for answering a simple question.

    You asserted that it's "unquestionably better". You can support
    that assertion or not. If you're not going to answer my question,
    an easier way to do that is to remain silent. I'm used to that
    from you.

    To be blunt, I don't care enough about your opinion to do extra
    work to extract it from you.
    --
    Keith Thompson (The_Other_Keith) [email protected]
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@[email protected] (Dan Cross) to comp.lang.c on Sat Oct 17 17:58:20 2026
    From Newsgroup: comp.lang.c

    In article <11avmfb$55rt$[email protected]>, bart <[email protected]> wrote:
    On 17/10/2026 04:19, Dan Cross wrote:
    In article <11auad0$3no1k$[email protected]>, bart <[email protected]> wrote:
    Those are considered more productive.

    ...and you think that's because of the syntax, and not the high
    level nature of those languages?

    It's a combination.

    Riiiight. C++ is widely considered "more productive" than C,
    and yet shares most of the syntactic warts you complain about so
    readily.

    Yes, the syntax is pretty gnarly; Dennis Ritchie even said as
    much. Fixed in Go and Rust, but also, I doubt you've ever in
    your life had a variable of type array of array of length 8 of
    a pointer to a pointer to a function returning an array of
    pointers to char. Finding the most ridiculous example you can
    is not really evidence of anything besides your weird obsession

    That was the first one I saw online next to a quote from K&R and I
    assumed it was from the book. In fact the example from the book is this:

    char (*(*x())[])()

    I've no idea what the means either. The point is not that the examples
    are ridiculous, but that they are hard to convert to and from LTR form
    which is how we think. With LTR syntax it becomes utterly trivial to
    read or write them, no matter how complex.

    (There's a tool called CDECL that translates types from C syntax to LTR >English or vice versa. It calls the C versions 'gibberish'. This is a
    real thing!)

    Yes. C's declaration syntax is famously abstruse; film at 11.

    with finding abstruse corner cases and holding them up as
    reasons to dislike C.

    The first example I gave was the simplest form of function pointer,
    where the syntax is 'void(*)(void)'. Hardly a corner case, and it
    rapidly goes downhill.

    Ok.

    If meeting C for the first time, that does not bode well. If the
    designers did not care about this, that does not inspire confidence in
    the rest of the language.

    Ok.

    If DMR had instead produced a language that looked like mine (say like
    one of the Algols), and I came along in 2026 and proposed a syntax that
    looked like the above, what do you think the response would be?

    But he didn't, and you didn't, so this is a meaningless
    historical, "what if?"

    You don't get the point.

    There does not appear to be one.

    If C had used LTR type syntax and somebody
    proposed using inside-out back-and-forth syntax like 'void(*)(void)',
    they'd think they were having a laugh, as it would be ridiculous.

    Unknowable.

    But this is exactly what I think about it anyway, no matter that 100
    million programs have battled with it for 50 years.

    Irrelevant.

    So being 'objective' means disregarding history and widespread adoption.

    Well, no...both of those are factors in choosing a language or
    not. We can discuss the semantics of the language, it's syntax,
    etc; but we can also discuss tooling, engineering resources
    availability (can you find programmers who know C? More like,
    can you find programmers who _don't_ know C, amirite?), library
    and platform support, and so on.

    Yes, this is my point; it is tolerated, and people learn to work with
    it. But how much extra effort has been expended, compared if they'd
    tried a bit harder to get a better language at the start? Or even during
    its first decade.

    Then your point is minor at best. Here's a thought experiment:
    suppose I suddenly came to my senses and agreed with everything
    you say: I'm willing to totally toss out C and adopt Bart's
    language yesterday. Where do I get a compiler? What learning
    resources exist? Oh, and I need it to generate code for an
    ARM Cortex-M0 part; does it do that? I also need RV64GC and
    x86_64 and probably aarch64, too. Might want to throw in
    Xtensa while we're at it: does your compiler do all of that?
    What if I need a debugger? Oh, and I need to use crypto
    libraries that are supplied from a vendor; they use the C ABI.
    What's the inter-op story like?

    Is C a good language? Meh, it's not the worst, but far from the
    best I've seen. Was it a bad language in 1972, when it was
    targeting a PDP-11/20? No, it was pretty decent for that era.

    Disagree.

    Really, the entire thread could be summed up in that one word,
    and it would save everyone a lot of time.

    Did it do all the stuff that fancy languages with advanced
    compilers that ran on big machines could do? No. Did it need
    to? Also no.

    I think C was first created for PDP7 with 4K words, then moved to PDP11 >(don't know the spec).

    No. That was B; the PDP-7 was an 18-bit word-oriented machine,
    and was archaic even in 1968 when they started using it. C was
    done on the PDP-11. An early cross-compilation environment on a
    GE-635 computer also existed, but the primary work on the
    language was on the 11/20 running Unix.

    You know, all of this is in Dennis Ritchie's C history paper,
    presented at SIGPLAN's HOPL-II, which is online. If you could
    get over yourself for like 20 minutes you could read it, and
    then not talk out your ass about history. https://www.nokia.com/bell-labs/about/dennis-m-ritchie/chist.html

    I suspect your general factual resistance is one of the several
    reasons so few people around here take you or your language
    seriously.

    [snip]
    My point is you can't excuse C being what it is due to hardware limitations.

    I used PDP11 quite a bit (/34) and that had a decent Fortran implementation.

    (A very different machine from an 11/20.)

    My own stuff was done in my spare time for no extra pay, on 8-bit
    machines I helped develop for my company, without the backing of Bell Labs.

    Good for you. Totally irrelevant to the history of C.

    Let me forestall the inevitable: you are going to reply and just
    repeat the same things over again. I don't care. None of this
    is an objective discussion of C; and it really comes across as
    you just seeking affirmation, which is genuinely sad.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Michael S@[email protected] to comp.lang.c on Sat Oct 17 21:03:59 2026
    From Newsgroup: comp.lang.c

    On Sat, 17 Oct 2026 18:23:47 +0100
    bart <[email protected]> wrote:

    On 17/10/2026 17:39, Michael S wrote:
    On Fri, 16 Oct 2026 15:00:27 -0700
    Keith Thompson <[email protected]> wrote:

    Tim Rentsch <[email protected]> writes:
    Keith Thompson <[email protected]> writes:
    I find "break NAME;", where "NAME" is the name of an enclosing
    construct, unambiguously better than "break N;", where N is the
    number of levels to break out of. [...]

    Definitely.

    There's a proposal for C2y to use goto labels as loop names, and
    a competing one to define a new syntax like "for NAME (;;)" :

    https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3355.htm
    https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3377.pdf

    I'm not particularly a fan of multi-level break/continue. But if
    we're going to have one of these, the second ("for NAME (;;)") is
    unquestionably better.

    Unquestionably? Why?


    I don't know why Tim prefers it.
    I prefer it (strongly) because it is different from regular label.
    So reader that wants to understand a flow of the program should not
    be concerned with possibility of jumping to it from places outside
    for().
    I do like the fact that it doesn't conflate goto labels with loop
    names, but I still prefer the "NAME: for (;;)" form, partly because
    it's consistent with several other languages.


    You mentioned itself that in Ada loop labels are distinct from
    regular labels. I would think that Ada alone easily outweighs
    "several other languages" if we compare by number (and likely by
    quality) of man-hours invested into thinking and discussion of
    syntactic features. Anyway I value appeal to success more than
    appeal to authority so by my own standards the argument above is
    weak.

    I was around when Ada was being developed and refined, a process that
    took years.

    By contrast, C looks like it was just thrown together with little
    thought, and probably that is exactly what happened.

    In the end, Ada was a language that you could admire, but you'd
    rather other people used. It's a solid language but I found it too
    formal and rather dull (not that it was available for me to use).


    I use Ada off-spring VHDL very regularly.
    I prefer it over Verilog, but I do it due to semantics and mostly
    despite [inherited from Ada] syntax.

    Still, I borrowed some syntactic features from it.

    One interesting fact that people might forget is that it was case-insensitive, a welcome difference IMV.


    I don't like case-insensitivity, except, may be, for keywords.
    I don't like begin..end.
    Most of all, I don't like nested procedures that have visibility of
    local variables of the parent (That's related to Ada, not significant
    in context of VHDL).
    I suppose, I don't like most of the thing that you like about
    programming languages.



    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Sat Oct 17 21:40:31 2026
    From Newsgroup: comp.lang.c

    On 17/10/2026 18:58, Dan Cross wrote:
    In article <11avmfb$55rt$[email protected]>, bart <[email protected]> wrote:
    On 17/10/2026 04:19, Dan Cross wrote:
    In article <11auad0$3no1k$[email protected]>, bart <[email protected]> wrote: >>>> Those are considered more productive.

    ...and you think that's because of the syntax, and not the high
    level nature of those languages?

    It's a combination.

    Riiiight.

    So greatly simplifying syntax, all other things being equal, does not
    increase productivity at all? Gotcha.

    Yes. C's declaration syntax is famously abstruse; film at 11.

    And ... that's it? Just accept it? How about doing something about it!

    I'm angry because to me C was so unusable that I had to create and
    maintain my own products over decades.

    Then I later found that C had insinuated itself into every API and every
    open source product I wanted to use. Even ABIs, supposedly
    language-neutral, pay deference to it. Even as a compiler target, there
    was no other choice.

    So I ended having to deal with it anyway, but thankfully avoided have to
    write it.


    If C had used LTR type syntax and somebody
    proposed using inside-out back-and-forth syntax like 'void(*)(void)',
    they'd think they were having a laugh, as it would be ridiculous.

    Unknowable.

    You do know; you just don't want to admit it. (Imagine introducing C declarations into a current language.)

    Then your point is minor at best. Here's a thought experiment:
    suppose I suddenly came to my senses and agreed with everything
    you say: I'm willing to totally toss out C and adopt Bart's
    language yesterday.

    THIS IS NOT ABOUT MY LANGUAGE!

    Why hasn't there long been an alternative systems language that didn't
    have C's crazy syntax and stupid quirks? I mean like 30-50 years ago.

    Yes, mine has lots of examples of how some alternative features could
    work; so what? I am not selling my language.


    Where do I get a compiler? What learning
    resources exist? Oh, and I need it to generate code for an
    ARM Cortex-M0 part; does it do that? I also need RV64GC and
    x86_64 and probably aarch64, too. Might want to throw in
    Xtensa while we're at it: does your compiler do all of that?
    What if I need a debugger? Oh, and I need to use crypto
    libraries that are supplied from a vendor; they use the C ABI.
    What's the inter-op story like?

    My language was for in-house use; it was never intended as a product.

    (If you really want to try it, I can supply an ASM file for you to
    build, but it works on Windows. I can no longer supply a transpiled C
    version that part work on Linux; I have destroyed my C-related projects.)

    The C API (not ABI) point is valid, and another bugbear. Why can't APIs
    be expressed in a language-agnostic manner? This would help other
    languages that also need to solve the problem of creating bindings to libraries that primarily use a C API.

    C is a terrible choice for a cross-language API, as too many C-isms
    creep in (like C macros, or vaguely defined types, including the famous
    'plain char' that exists in no other language, which is neither signed
    nor unsigned, and above all C preprocessor features).

    Good for you. Totally irrelevant to the history of C.

    It means that meagre hardware resources don't have to compromise the
    design of a language, especially when it comes to syntax.

    So you can't use limited resources as an excuse for its questionable
    choices. Actually some choices actually made it harder to parse.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Tim Rentsch@[email protected] to comp.lang.c on Sat Oct 17 19:25:54 2026
    From Newsgroup: comp.lang.c

    [email protected] (Waldek Hebisch) writes:

    Lawrence D?Oliveiro <[email protected]d> wrote:

    On Tue, 13 Oct 2026 07:23:40 -0000 (UTC), Waldek Hebisch wrote:

    So what those counts indicate: majority of loops is simple, that is
    have no early exit. Vast majority of early exits is done via
    'return'.

    My experience in my own C code is quite the opposite. Lots of loops
    have exits in the middle, leading me to use forms like ?for (;;)?. I
    also try to avoid putting ?return? anywhere other than the end of a
    function, to make it easier to see the flow of control.

    Well, usually there is a lot of loops. Those with exit in the
    middle are still significant.

    Concernig 'return', having it in place where all work inside function
    is done help me to see flow control and avoids complications. In
    case of search functions it means return from the middle of the loop.
    IMO possible alternatives like flag variables or break and retrun
    after loop are worse.

    I rarely use 'break' to exit a loop. Part of this is that I try to
    write standard loops so that they complete as part of the loop test
    (i.e., in while() or for() control expressions). That isn't the
    whole story though so let me talk about 'return'.

    Most of the functions I write have exactly one return, at the end of
    the function. I estimate this pattern accounts for around 85% of
    all functions, let's say plus or minus 5%.

    Sometimes functions have early returns for errors or exceptional
    conditions. Early returns are easily seen to lie outside the main
    body of function processing so they don't interfere with
    understanding what the rest of the function is doing or how it
    works.

    A fairly common sub-pattern are functions most of whose body is a
    switch() statement, with all of the switch() cases being a simple
    return.

    It does sometimes happen that a function will have a loop with a
    return in the middle, and also a return at the end for what to do if
    the loop terminates. To me having an in-loop return looks better
    than using an assignment and a break.

    A fairly rare but important pattern is what I might call vectoring
    or decomposition. Here the function body serves to distinguish and
    separate out different regimes of subprocessing. To continue
    processing in a particular regime, a return is used not to directly
    yield a value but rather to call a further function to handle that
    sub-domain. The benefit here is both to keep function bodies small
    and to allow re-use of commonly called sub-functions.

    Two aspects are important for having these different styles work
    together. One is that it's easy to distinguish the different kinds
    of patterns, and by far the most simple pattern is the most common.
    The other is to be sure to keep function bodies small. Keeping
    function bodies small goes a long way in making them easy to
    understand, which obviously is a key property in writing good code.
    Also keeping function bodies small effectively prevents mixing
    different styles in a single function, serving to reinforce point
    one.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@[email protected] to comp.lang.c on Sun Oct 18 12:38:51 2026
    From Newsgroup: comp.lang.c

    On 16/10/2026 23:46, Scott Lurndal wrote:
    Lawrence =?iso-8859-13?q?D=FFOliveiro?= <[email protected]d> writes:
    On Fri, 16 Oct 2026 15:24:01 -0000 (UTC), Waldek Hebisch wrote:

    Concernig 'return', having it in place where all work inside
    function is done help me to see flow control and avoids
    complications. In case of search functions it means return from the
    middle of the loop. IMO possible alternatives like flag variables or
    break and retrun after loop are worse.

    Code tends to do a lot of dynamic resource allocation these days, and
    that requires cleanup. Doing a direct “return” from the middle of a
    function body doesn’t allow for that.

    Unless you use a GCC extension like “defer”, I suppose.

    "defer" is not a gcc extension. You can "defer" macro, using gcc's
    "cleanup" attribute (which /is/ an extension) :

    <https://gustedt.gitlabpages.inria.fr/defer/>

    As I understand it, "defer" is in the proposal stage and could make it
    into C2y, but it is not yet in the draft standard. There are test implementations in gcc, clang, and a couple of other compilers.


    Better to use the cleanup attribute (or RAII in C++).

    #define RAII_CHM __attribute__((cleanup(auto_free_ptr)))
    #define RAII_FILE __attribute__((cleanup(auto_close_file)))

    int main(void) {
    // Memory and file handles are bound to this block scope
    RAII_CHM char *buffer = malloc(100);
    RAII_FILE FILE *fp = fopen("example.txt", "w");

    if (!buffer || !fp) {
    return -1; // Even on early exit, validly opened resources are cleaned up!
    }

    fprintf(fp, "Hello, RAII in C!");

    return 0; // Both buffer and fp are automatically freed/closed here
    }

    "defer" has a number of benefits over "cleanup", but "cleanup" has the advantage that it is available now on gcc and clang - if portability is
    not an issue.

    Still, I would not write code like you show above - in C, people expect
    more explicit code, and you are hiding non-standard C behaviour with
    somewhat obscure names. (Obscurity is, of course, dependent on how much
    you use the feature in your code.)

    I'd rather have :

    #define RAII(cleanup_func) __attribute__((cleanup(cleanup_func)))

    RAII(auto_free_ptr) char * buffer = malloc(100);
    RAII(auto_close_file) FILE * fp = fopen("example.txt", "w");



    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@[email protected] to comp.lang.c on Sun Oct 18 12:48:31 2026
    From Newsgroup: comp.lang.c

    On 17/10/2026 01:29, Janis Papanagnou wrote:
    On 2026-10-17 00:00, Keith Thompson wrote:
    Tim Rentsch <[email protected]> writes:
    Keith Thompson <[email protected]> writes:
    [...]
    There's a proposal for C2y to use goto labels as loop names, and a
    competing one to define a new syntax like "for NAME (;;)" :
    [...]

    I'm not particularly a fan of multi-level break/continue.  But if
    we're going to have one of these, the second ("for NAME (;;)") is
    unquestionably better.

    Unquestionably?  Why?

    Why would one question an opinion? ;-)

    Time didn't word it as a personal opinion - he made it clear that he
    doesn't think anyone else could have a different opinion.

    The C standards committee collectively reached an agreement counter to
    Tim's thoughts, so clearly his preferred variant is /not/ unquestionably better.



    I do like the fact that it doesn't conflate goto labels with loop
    names, but I still prefer the "NAME: for (;;)" form, partly because
    it's consistent with several other languages.

    I've no strong opinion on that, but I find the "for NAME (;;)" to
    clearer express the _local scope_ of embedded breaks or continues.
    (Just a matter of taste, and my appreciation for locality.)


    A main objection to "name: for ..." is that with function-scope labels,
    you need a new name for every labelled loop or switch. That may be an inconvenience, especially for macro with labelled loops, or for
    copy-and-paste code. There is a proposal to deal with that which
    basically says :

    1. Any "break label;" or "continue label;" refers to the innermost
    containing loop or switch with that label.

    2. Any "label" used in "goto label;" must be unique in the function.

    Those rules give a simple and intuitive fix without affecting existing code.

    Beyond that, "name: for ..." or "for name ..." is, as you say, mostly a
    matter of taste. (There are proposals for both versions, and you can
    look them up to see the arguments.)


    As far as I recall, in "C", the name of the function was often put
    separately (first in the line) to have an easy method to find its
    declaration by simple "grep ^fname". (With any sophisticated editor
    this might be a weak argument, though.)


    I think it was popularised with a shortcut in emacs.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Sun Oct 18 12:04:18 2026
    From Newsgroup: comp.lang.c

    On 18/10/2026 11:48, David Brown wrote:
    On 17/10/2026 01:29, Janis Papanagnou wrote:

    I've no strong opinion on that, but I find the "for NAME (;;)" to
    clearer express the _local scope_ of embedded breaks or continues.
    (Just a matter of taste, and my appreciation for locality.)


    A main objection to "name: for ..." is that with function-scope labels,
    you need a new name for every labelled loop or switch.  That may be an inconvenience, especially for macro with labelled loops, or for copy- and-paste code.  There is a proposal to deal with that which basically
    says :

    1. Any "break label;" or "continue label;" refers to the innermost containing loop or switch with that label.

    2. Any "label" used in "goto label;" must be unique in the function.

    Those rules give a simple and intuitive fix without affecting existing
    code.


    There's something missing. Labels usually live in their own,
    function-wide name space.

    But if you have two loops like this:

    L1: while () {} L2:
    L1: while () {} L2:

    Then even if no gotos exist to L1, is that rule somehow relaxed for
    those L1s to allow them to co-exist? (While still applying to non-loop
    labels L2, which would clash.)

    Will the L1s still live within the regular name space? (Presumably each
    will now be tagged with its associated loop.)

    Beyond that, "name: for ..." or "for name ..." is, as you say, mostly a matter of taste.  (There are proposals for both versions, and you can
    look them up to see the arguments.)

    The second form allows for those label names to be special, for example
    by belonging in the same name space as regular identifiers and thus
    subject to block scope rules. This is a tidier solution to the above.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@[email protected] to comp.lang.c on Sun Oct 18 13:22:52 2026
    From Newsgroup: comp.lang.c

    On 17/10/2026 13:34, bart wrote:
    On 17/10/2026 04:19, Dan Cross wrote:
    In article <11auad0$3no1k$[email protected]>, bart  <[email protected]> wrote:

    Those are considered more productive.

    ...and you think that's because of the syntax, and not the high
    level nature of those languages?

    It's a combination.

    Yes, the syntax is pretty gnarly; Dennis Ritchie even said as
    much.  Fixed in Go and Rust, but also, I doubt you've ever in
    your life had a variable of type array of array of length 8 of
    a pointer to a pointer to a function returning an array of
    pointers to char.  Finding the most ridiculous example you can
    is not really evidence of anything besides your weird obsession

    That was the first one I saw online next to a quote from K&R and I
    assumed it was from the book. In fact the example from the book is this:

      char (*(*x())[])()

    I've no idea what the means either. The point is not that the examples
    are ridiculous, but that they are hard to convert to and from LTR form
    which is how we think. With LTR syntax it becomes utterly trivial to
    read or write them, no matter how complex.

    (There's a tool called CDECL that translates types from C syntax to LTR English or vice versa. It calls the C versions 'gibberish'. This is a
    real thing!)


    Putting that example in cdecl gives :

    "declare x as function returning pointer to array of pointer to function returning char"

    To me, that is just as much gibberish as the original C. No syntax is
    going to make sense of it - no amount of "ref" or "func" or pre-fix
    array notation will help.

    If you want complex types in a programming language, make them out of
    simpler, named types that express what you are trying to achieve. I
    think any decent typed programming language will have a way to do this -
    for C, "typedef" is your friend here.

    (And do /not/ reply by bringing up examples you have cherry-picked from
    code you have found, as though it was my fault they wrote
    incomprehensible code.)



    with finding abstruse corner cases and holding them up as
    reasons to dislike C.

    The first example I gave was the simplest form of function pointer,
    where the syntax is 'void(*)(void)'. Hardly a corner case, and it
    rapidly goes downhill.

    Name the types at the point where they are clear, and build them up from there.

    typedef void (*fp_void)(void);




    If meeting C for the first time, that does not bode well. If the
    designers did not care about this, that does not inspire confidence in
    the rest of the language.

    C is not, and has never claimed to be, a beginner-friendly language. It
    is designed to be efficient while remaining quite a small language,
    which means that there are parts that are harder to use correctly,
    details that are important to understand, and it has plenty of scope to
    write code that is unclear. It works well for responsible programmers
    who learn the language and code carefully - but you have to learn more
    before you can understand and use it than, say, BASIC or Python.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@[email protected] to comp.lang.c on Sun Oct 18 13:39:58 2026
    From Newsgroup: comp.lang.c

    On 2026-10-18 12:48, David Brown wrote:
    On 17/10/2026 01:29, Janis Papanagnou wrote:
    On 2026-10-17 00:00, Keith Thompson wrote:
    Tim Rentsch <[email protected]> writes:
    Keith Thompson <[email protected]> writes:
    [...]
    There's a proposal for C2y to use goto labels as loop names, and a
    competing one to define a new syntax like "for NAME (;;)" :
    [...]

    I'm not particularly a fan of multi-level break/continue.  But if
    we're going to have one of these, the second ("for NAME (;;)") is
    unquestionably better.

    Unquestionably?  Why?

    Why would one question an opinion? ;-)

    Time didn't word it as a personal opinion - he made it clear that he
    doesn't think anyone else could have a different opinion.

    You've noticed my smiley? (There was no need for an explanation.)


    The C standards committee collectively reached an agreement counter to
    Tim's thoughts, so clearly his preferred variant is /not/ unquestionably better.

    "C" is "C", and Tim is Tim. (And we know both sufficiently.) :-)




    I do like the fact that it doesn't conflate goto labels with loop
    names, but I still prefer the "NAME: for (;;)" form, partly because
    it's consistent with several other languages.

    I've no strong opinion on that, but I find the "for NAME (;;)" to
    clearer express the _local scope_ of embedded breaks or continues.
    (Just a matter of taste, and my appreciation for locality.)


    (I interpret your following explanations as additional information.)

    A main objection to "name: for ..." is that with function-scope labels,
    you need a new name for every labelled loop or switch.  That may be an inconvenience, especially for macro with labelled loops, or for copy- and-paste code.  There is a proposal to deal with that which basically
    says :

    1. Any "break label;" or "continue label;" refers to the innermost containing loop or switch with that label.

    2. Any "label" used in "goto label;" must be unique in the function.

    Those rules give a simple and intuitive fix without affecting existing
    code.

    Yes.


    Beyond that, "name: for ..." or "for name ..." is, as you say, mostly a matter of taste.  (There are proposals for both versions, and you can
    look them up to see the arguments.)

    Thanks. I'm interested, but (given what I think about it) not that
    much. :-)



    As far as I recall, in "C", the name of the function was often put
    separately (first in the line) to have an easy method to find its
    declaration by simple "grep ^fname". (With any sophisticated editor
    this might be a weak argument, though.)


    I think it was popularised with a shortcut in emacs.

    Well, I don't know what Emacs supports, or what it doesn't support so
    that it requires some workaround, or shortcut, or explicit help from
    the programmers concerning the layout.

    I was using Vi for decades and with a search command ('/') you can do
    a regexp '/^fname' to find fname at the start of a line. But there's
    also "ctags" that can be used to facilitate that (and more). Recently
    (i.e. since 25+ years) I'm using Vim where there's additional facilities
    like the commands 'gd' (and 'gD') to jump to the local (and "global") declaration of an entity; the latter don't require a tags-database or
    any specific source code formatting to find the names.

    Personally I've never followed the function-type-on-an-own-line style.

    Janis

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@[email protected] to comp.lang.c on Sun Oct 18 14:09:52 2026
    From Newsgroup: comp.lang.c

    On 18/10/2026 13:04, bart wrote:
    On 18/10/2026 11:48, David Brown wrote:
    On 17/10/2026 01:29, Janis Papanagnou wrote:

    I've no strong opinion on that, but I find the "for NAME (;;)" to
    clearer express the _local scope_ of embedded breaks or continues.
    (Just a matter of taste, and my appreciation for locality.)


    A main objection to "name: for ..." is that with function-scope
    labels, you need a new name for every labelled loop or switch.  That
    may be an inconvenience, especially for macro with labelled loops, or
    for copy- and-paste code.  There is a proposal to deal with that which
    basically says :

    1. Any "break label;" or "continue label;" refers to the innermost
    containing loop or switch with that label.

    2. Any "label" used in "goto label;" must be unique in the function.

    Those rules give a simple and intuitive fix without affecting existing
    code.



    For reference:

    <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3658.htm>

    There's something missing. Labels usually live in their own, function-
    wide name space.

    But if you have two loops like this:

       L1: while () {} L2:
       L1: while () {} L2:

    Then even if no gotos exist to L1, is that rule somehow relaxed for
    those L1s to allow them to co-exist? (While still applying to non-loop labels L2, which would clash.)

    Fair questions.

    The rules (as given in proposal N3658) apply to all labels.

    The point of the proposal is to look at how the labels are /used/, not
    how they are defined, and make sure their /use/ is clear, intuitive,
    intended, and unambiguous.

    The two "L2:" labels above would not be a problem unless there is a
    "goto L2" somewhere - then it is unclear which "L2" is being referenced,
    and it is the use of "goto L2" that means the duplication is flagged as
    an error.

    The two "L1:" labels above would also constitute an error if you have
    "goto L1" in the function.

    But if you have "break L1" or "continue L1" within the body of one of
    the loops, it is entirely clear which L1 is being referred to - and thus
    there is no error.



    Will the L1s still live within the regular name space? (Presumably each
    will now be tagged with its associated loop.)

    No - with this change, labels do not have "scope" in the same way as
    before, but context-dependent lookup.

    Note that if you have "L1: while () {}", and no other label "L1", then
    you can happily use "goto L1" from anywhere in the function (assuming
    you don't fall foul of other rules) - the label "L1" is /not/ in a local
    scope within the loop.


    Beyond that, "name: for ..." or "for name ..." is, as you say, mostly
    a matter of taste.  (There are proposals for both versions, and you
    can look them up to see the arguments.)

    The second form allows for those label names to be special, for example
    by belonging in the same name space as regular identifiers and thus
    subject to block scope rules. This is a tidier solution to the above.


    Yes, the "for name ..." form makes label names special. No, it is not a "tidier solution" - though of course you are welcome to a personal
    opinion that you think one syntax variant is nicer than the other.
    There are pros and cons of each syntax - that's why its important that
    there is a committee (two committees, actually, since both C and C++ are working on this) rather than having one person declare "this is clearly
    the best". (Just so you know I am not picking on you - in another post
    I also said Tim was wrong to say "for name ..." was "unquestionably
    better". And I am /not/ suggesting that "label: for ..." is
    unquestionably better either.)


    See :

    <https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3568r0.html#opposition-to-n3377>

    (That is a C++ proposal, but discussions have gone back and forth
    between both C and C++ standards groups because the changes can apply to
    both languages - and no one wants different syntaxes for identical
    features.)


    A key point is that labels of the form "L1: ..." are already familiar in
    C and many other programming languages, and a large number of other
    languages support something akin to "L1: while (..) { ... break L1; }".

    Additionally, "L1 : do { ... break L1; } while (...)" puts the name at
    the top of the loop, rather than at the end (if it is attached to the "while"). (I don't know why N3377 proposed "do { } while NAME ( )"
    rather than "do NAME { } while ( )". )


    And for those that like to use macros for their loops, the prefix label
    is neater:

    #define FOR_LOOP(_i, _n) for (int _i; i = 0; i < _n)

    outer : FOR_LOOP(i, 100) {
    inner : FOR_LOOP(j, 100) {
    if (i * j == 45) break outer;
    }
    }






    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@[email protected] to comp.lang.c on Sun Oct 18 14:12:54 2026
    From Newsgroup: comp.lang.c

    On 2026-10-18 13:22, David Brown wrote:
    On 17/10/2026 13:34, bart wrote:
    [...]
       char (*(*x())[])()
    [...]

    Putting that example in cdecl gives :

    "declare x as function returning pointer to array of pointer to function returning char"

    There's different things here with the C-declaration.
    * Complexity of expression; as you say below this can be alleviated by
    structuring with "subtypes" and 'typedef'.
    * Cryptic syntax with many (spurious but in "C" necessary) parenthesis.
    * Mixed/mangled order of component concerning its logical structure.

    The 'cdecl' tool helps with point 2 and 3. - So I consider it to be
    quite useful! (Although I have to admit that I've never used it myself
    in practice because (for my code) I try to not compose overly complex
    type definitions; and when it gets complex point 1 applies.) Especially
    if you have to work with third-party code it can spare you some time,
    though.


    To me, that is just as much gibberish as the original C.  No syntax is going to make sense of it - no amount of "ref" or "func" or pre-fix
    array notation will help.

    I assume you're here commenting on some of bart's adopted syntactical decisions.

    FWIW; why I prefer some other language design decisions is exactly that
    they use syntaxes with such keywords. They typically reduce the number
    of parentheses and other "graph" characters thereby reducing the effect
    of code appearing quickly more cryptic than necessary, they make the
    definition more clear and better readable (IMO). Keeping (in addition)
    the logical order of its components also helps IMO to easier understand
    the declaration construct.

    To be frank, it's beyond me why anyone wouldn't admire such consistent declaration syntaxes. (And if bart has adopted those principles that's certainly not a bad thing. YMMV.)


    If you want complex types in a programming language, make them out of simpler, named types that express what you are trying to achieve.  I
    think any decent typed programming language will have a way to do this -
    for C, "typedef" is your friend here.

    Yes. This is what we can do about the "complexity" aspect of the topic.

    Janis

    [snip]

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@[email protected] to comp.lang.c on Sun Oct 18 14:18:08 2026
    From Newsgroup: comp.lang.c

    On 16/10/2026 23:22, Tim Rentsch wrote:
    Keith Thompson <[email protected]> writes:

    I find "break NAME;", where "NAME" is the name of an enclosing
    construct, unambiguously better than "break N;", where N is the
    number of levels to break out of. [...]

    Definitely.

    There's a proposal for C2y to use goto labels as loop names, and a
    competing one to define a new syntax like "for NAME (;;)" :

    https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3355.htm
    https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3377.pdf

    I'm not particularly a fan of multi-level break/continue. But if
    we're going to have one of these, the second ("for NAME (;;)") is unquestionably better.

    Given the number of questions asked, the various proposals for labelled
    break and continue in both C and C++, and the fact that the C standards committee have already chosen "name: for (...)" as their syntax, you are unquestionably wrong to say that the second form is "unquestionably
    better". Indeed, you would also have been wrong had you said the first
    form is "unquestionably better".

    You can have your opinion, and you can have justification for that
    opinion, but it is not fact, and it is not unquestionable. There are
    pros and cons of both variants, and different people will put different weightings on which of those are most important to them personally - or
    which they think will be most important for the language and programmer community in general.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@[email protected] to comp.lang.c on Sun Oct 18 14:32:59 2026
    From Newsgroup: comp.lang.c

    On 17/10/2026 22:40, bart wrote:
    On 17/10/2026 18:58, Dan Cross wrote:
    In article <11avmfb$55rt$[email protected]>, bart  <[email protected]> wrote:
    On 17/10/2026 04:19, Dan Cross wrote:
    In article <11auad0$3no1k$[email protected]>, bart  <[email protected]>
    wrote:

    Yes.  C's declaration syntax is famously abstruse; film at 11.

    I'm not sure it is. It is different from what you find in some other languages, and it is certainly possible to write declarations in C that
    are hard to comprehend. But it is possible to do that in any
    programming language, and equally you can write clear declarations in C.
    It is very rare that I have to think about the syntax of declarations
    when I write C code, or when I read C code - maybe that's just my own experience, but it is simply not an issue for me. Mind you, I don't
    write code with the rubbish that you bring up as "examples" - maybe my experience is different from that of other people.


    And ... that's it? Just accept it? How about doing something about it!


    What, exactly, do you think any of us should do about it? Let's hear a
    clear, realistic, concrete plan for how people here, the readers of comp.lang.c, can go about changing the syntax for C declarations.

    Note that continually posting complaints to people who did not design
    the C language, do not implement C compilers, and are not part of the C standards committee, is not a realistic or concrete plan for change.

    Nor is continually badgering people to "admit" that C is a terrible
    language.




    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@[email protected] to comp.lang.c on Sun Oct 18 14:34:28 2026
    From Newsgroup: comp.lang.c

    On 2026-10-18 14:09, David Brown wrote:

    [...]  (I don't know why N3377 proposed "do { } while NAME ( )"
    rather than "do NAME { } while ( )". )

    Oh! - I can only think that it would then be (sort of) "consistent"
    with the place of the label attacked in a 'while' loop; i.e. behind
    the 'while' keyword. - It's inconsistent in another interpretation,
    though; and I'd certainly have favored the latter form, to have the
    label consistently attached at the loop-entry keyword.
    We'll see what they finally decide (unless it's already clear; I'm
    not sure about the factual weight of the "proposal")...

    Janis

    [...]

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Sun Oct 18 14:33:25 2026
    From Newsgroup: comp.lang.c

    On 18/10/2026 12:22, David Brown wrote:
    On 17/10/2026 13:34, bart wrote:
    On 17/10/2026 04:19, Dan Cross wrote:
    In article <11auad0$3no1k$[email protected]>, bart  <[email protected]> wrote: >>
    Those are considered more productive.

    ...and you think that's because of the syntax, and not the high
    level nature of those languages?

    It's a combination.

    Yes, the syntax is pretty gnarly; Dennis Ritchie even said as
    much.  Fixed in Go and Rust, but also, I doubt you've ever in
    your life had a variable of type array of array of length 8 of
    a pointer to a pointer to a function returning an array of
    pointers to char.  Finding the most ridiculous example you can
    is not really evidence of anything besides your weird obsession

    That was the first one I saw online next to a quote from K&R and I
    assumed it was from the book. In fact the example from the book is this:

       char (*(*x())[])()

    I've no idea what the means either. The point is not that the examples
    are ridiculous, but that they are hard to convert to and from LTR form
    which is how we think. With LTR syntax it becomes utterly trivial to
    read or write them, no matter how complex.

    (There's a tool called CDECL that translates types from C syntax to
    LTR English or vice versa. It calls the C versions 'gibberish'. This
    is a real thing!)


    Putting that example in cdecl gives :

    "declare x as function returning pointer to array of pointer to function returning char"

    To me, that is just as much gibberish as the original C.

    That doesn't matter - the problem is not even knowing what it
    represents. (That it is an actual function is a surprise. That you can't easily tell is crazy.)

    In practice there will be actual types that start to look like
    gibberish, full of *, () and [] that must be in exactly the right place.

    Then maybe you want to construct a pointer to such a type or an array of
    it - where will be the new * or [] go? Where will the variable name go
    for that matter?

    This should be simple enough to do in a language without needing to
    follow some back-and-forth algorithm, or use an external tool, or need
    to decompose them into multiple levels using 'typedef', or need to disambiguate with parentheses.

    Typedef decomposition can be useful when types are genuinely complex (or
    parts of them are used/shared elsewhere), but it should not be a crutch
    for an unusable type syntax.

    In any case, for me the threshold at which I need help is low. I
    couldn't do these for example:

    * Array of function pointers (say taking no params and returning void)
    * Pointer to array of function pointers
    * Function returning pointer to array (of int)
    * Pointer to function returning pointer to array (int)

    My tool tells me the answers are these:

    void (*[])(void)
    void (*(*)[])(void)
    int (*(void))[]
    int (*(*)(void))[]

    Still gobbledygook, sorry, and these are hardly that complex or
    unrealistic. (Other than 'pointer to array' being an uncommon C idiom.
    It's only uncommon because other C syntax choices make it ungainly to
    work with.)

    Of those four lines, one is an actual function; another is a pointer to
    a function. Plus there is an array, and a pointer to something else. But
    this is not obvious at a glance, because the key part is buried in the
    middle. In an LTR scheme, it would be first.

     No syntax is
    going to make sense of it - no amount of "ref" or "func" or pre-fix
    array notation will help.

    It will tell you what it is, which is a start. Those four examples I
    gave would look like this:

    []ref proc # 'proc' is 'func -> void'
    ref []ref proc
    func -> ref []int
    ref func -> ref []int

    Using a scheme I once proposed for C, to work side-by-side with the
    current syntax, I believe it would be like this:

    []*func()void
    *[]*func()void p, q;
    func F()*[]int {}
    *func()*[]int

    Variable names would go on the right as in the second example. For that
    actual function however, an earlier name looks better and matches other languages.

    If you want complex types in a programming language, make them out of simpler, named types that express what you are trying to achieve.  I
    think any decent typed programming language will have a way to do this -
    for C, "typedef" is your friend here.

    (And do /not/ reply by bringing up examples you have cherry-picked from
    code you have found, as though it was my fault they wrote
    incomprehensible code.)

    But that is going to happen. You will come across such types.

    C is not, and has never claimed to be, a beginner-friendly language.

    If something is needlessly complex and unintuitive, that will be the
    case for everyone.

    For beginners to C, it is just an unnecessary obstacle. I can see many
    giving up on it for that reason.

    One way to simplify types is to use 'typeof' (I've no idea whether it is
    still an extension or now standardised). That means being able to write:

    typeof(int*) p, q, r;

    instead of: 'int *p, *q, *r' which is too tempting to write as 'int* p,
    q, r'.

    This solves another issue where the type of any declared variable is
    split up into up three pieces in three different places:

    int a, b, *c[10];


    The type of 'c' comprises 'int', '*' before the name, and '[]' after the
    name. This makes it hard to share too. 'typeof' allows this (or along
    these lines):

    typeof(int*[]) x, y, z;

    The type is in one tidy place, and it can be shared. This is how C
    should have worked in the first place, and it wouldn't have needed that
    untidy 'typeof()'.


      It
    is designed to be efficient while remaining quite a small language,

    C's type declarations are actually harder to parse than a conventional
    LTR scheme. That means a more complex compiler front-end.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Michael S@[email protected] to comp.lang.c on Sun Oct 18 17:13:39 2026
    From Newsgroup: comp.lang.c

    On Sun, 18 Oct 2026 14:34:28 +0200
    Janis Papanagnou <[email protected]> wrote:
    On 2026-10-18 14:09, David Brown wrote:

    [...]� (I don't know why N3377 proposed "do { } while NAME ( )"
    rather than "do NAME { } while ( )". )

    Oh! - I can only think that it would then be (sort of) "consistent"
    with the place of the label attacked in a 'while' loop; i.e. behind
    the 'while' keyword. - It's inconsistent in another interpretation,
    though; and I'd certainly have favored the latter form, to have the
    label consistently attached at the loop-entry keyword.
    I'd prefer label consistently attached to the loop-exit keyword.
    Unfortunately, for() and while() loops have no such keyword.
    We'll see what they finally decide (unless it's already clear; I'm
    not sure about the factual weight of the "proposal")...

    I tend to agree with Tim (if I correctly understood him): a.t.m. the
    best outcome would be proposal scrapped completely.
    Janis

    [...]

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Michael S@[email protected] to comp.lang.c on Sun Oct 18 17:24:46 2026
    From Newsgroup: comp.lang.c

    On Sun, 18 Oct 2026 13:22:52 +0200
    David Brown <[email protected]> wrote:


    To me, that is just as much gibberish as the original C. No syntax
    is going to make sense of it - no amount of "ref" or "func" or
    pre-fix array notation will help.


    [O.T.]
    Prefix array notation would not. But postfix * notation would, somewhat.

    It would be interesting to find out why designers of C, or of one of its ancestors decided that * as prefix is preferable to * as postfix.
    Were they afraid of confusion with usage of * as multiplication?
    Probably not, because confusion can arise about equally both for prefix
    and for postfix.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@[email protected] to comp.lang.c on Sun Oct 18 16:27:18 2026
    From Newsgroup: comp.lang.c

    On 18/10/2026 15:33, bart wrote:
    On 18/10/2026 12:22, David Brown wrote:
    On 17/10/2026 13:34, bart wrote:
    On 17/10/2026 04:19, Dan Cross wrote:
    In article <11auad0$3no1k$[email protected]>, bart  <[email protected]>
    wrote:

    Those are considered more productive.

    ...and you think that's because of the syntax, and not the high
    level nature of those languages?

    It's a combination.

    Yes, the syntax is pretty gnarly; Dennis Ritchie even said as
    much.  Fixed in Go and Rust, but also, I doubt you've ever in
    your life had a variable of type array of array of length 8 of
    a pointer to a pointer to a function returning an array of
    pointers to char.  Finding the most ridiculous example you can
    is not really evidence of anything besides your weird obsession

    That was the first one I saw online next to a quote from K&R and I
    assumed it was from the book. In fact the example from the book is this: >>>
       char (*(*x())[])()

    I've no idea what the means either. The point is not that the
    examples are ridiculous, but that they are hard to convert to and
    from LTR form which is how we think. With LTR syntax it becomes
    utterly trivial to read or write them, no matter how complex.

    (There's a tool called CDECL that translates types from C syntax to
    LTR English or vice versa. It calls the C versions 'gibberish'. This
    is a real thing!)


    Putting that example in cdecl gives :

    "declare x as function returning pointer to array of pointer to
    function returning char"

    To me, that is just as much gibberish as the original C.

    That doesn't matter - the problem is not even knowing what it
    represents.

    That is, shall we say, a strange attitude. Gibberish (since that seems
    to be the preferred term here) is gibberish, no matter the language or representation, and is equally meaningless and useless.

    (That it is an actual function is a surprise. That you can't
    easily tell is crazy.)

    You can tell it very easy from the C - the final bit is parentheses.


    In practice there will be actual types that start to look like
    gibberish, full of *, () and [] that must be in exactly the right place.

    Not in my code, or the code I work with - types are clear to me. Again, experiences can vary. (Of course the syntactical elements must be in
    the right place!)


    Then maybe you want to construct a pointer to such a type or an array of
    it - where will be the new * or [] go? Where will the variable name go
    for that matter?

    Use a typedef. Or since C23, use type inference - that can save naming
    and identifying types when things get complex, and makes it easier to
    write more general code. Like all language features, there are times
    when it is appropriate, and times when it is inappropriate. But if
    you've got something "foo" (an object, function, type, etc.) and you
    want an array of 26 of that type, type inference makes that simple - the
    type of "foo" is "typeof(foo)" :

    typeof(foo) xs[26];

    If you want a pointer to the object "foo", "auto * p = &foo;". This is,
    IMHO, a nice addition in C23, but it would have been nicer to have had
    it earlier. (It's been a gcc extension for a long time.)


    This should be simple enough to do in a language without needing to
    follow some back-and-forth algorithm, or use an external tool, or need
    to decompose them into multiple levels using 'typedef', or need to disambiguate with parentheses.

    You just /have/ to whine, don't you? Whenever you complain - usually
    due to ignorance or prejudice - that something is difficult or
    complicated in C, and someone tells you how it can be handled simply and clearly, you are unable to simply say "Okay, thanks - that's good to
    know" or "Sorry, I was wrong, I thought it was hard". You can't help
    but call things workarounds, or complicated, or get your knickers in a
    twist about having to use a language feature that for some reason you hate.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@[email protected] to comp.lang.c on Sun Oct 18 16:52:17 2026
    From Newsgroup: comp.lang.c

    On 18/10/2026 16:13, Michael S wrote:
    On Sun, 18 Oct 2026 14:34:28 +0200
    Janis Papanagnou <[email protected]> wrote:

    On 2026-10-18 14:09, David Brown wrote:

    [...]  (I don't know why N3377 proposed "do { } while NAME ( )"
    rather than "do NAME { } while ( )". )

    Oh! - I can only think that it would then be (sort of) "consistent"
    with the place of the label attacked in a 'while' loop; i.e. behind
    the 'while' keyword. - It's inconsistent in another interpretation,
    though; and I'd certainly have favored the latter form, to have the
    label consistently attached at the loop-entry keyword.

    I'd prefer label consistently attached to the loop-exit keyword. Unfortunately, for() and while() loops have no such keyword.


    That would help for switch inside a loop, or loop inside a switch, but
    do nothing for loop inside a loop or switch inside a switch. I don't
    think anyone involved in the development of the language has seriously considered making a solution that only handles the first two cases, and
    not the second two (to say nothing of three or more nesting layers). "break_switch" and "break_loop" style solutions have been mentioned and quickly dismissed, along with the "break <depth>" options.

    We'll see what they finally decide (unless it's already clear; I'm
    not sure about the factual weight of the "proposal")...


    I tend to agree with Tim (if I correctly understood him): a.t.m. the
    best outcome would be proposal scrapped completely.


    The proposal has been accepted - it is coming to C and C++, whatever you
    or Tim may think. But of course there is no requirement to /use/ the
    new feature if you don't like it. (I don't expect to use it
    significantly myself - I just don't seem to write code in a way that
    could take advantage of it.)

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@[email protected] to comp.lang.c on Sun Oct 18 16:58:38 2026
    From Newsgroup: comp.lang.c

    On 18/10/2026 16:24, Michael S wrote:
    On Sun, 18 Oct 2026 13:22:52 +0200
    David Brown <[email protected]> wrote:


    To me, that is just as much gibberish as the original C. No syntax
    is going to make sense of it - no amount of "ref" or "func" or
    pre-fix array notation will help.


    [O.T.]
    Prefix array notation would not. But postfix * notation would, somewhat.


    I can agree that notational changes might make it marginally easier to understand complex declarations - or mean that declarations could be marginally more complex while still being easily understood. But
    nothing can make Bart's exaggerated examples meaningful.

    It would be interesting to find out why designers of C, or of one of its ancestors decided that * as prefix is preferable to * as postfix.
    Were they afraid of confusion with usage of * as multiplication?
    Probably not, because confusion can arise about equally both for prefix
    and for postfix.


    I don't know why it is prefix. Maybe they were keen on "*p++ = *q++"
    and similar expressions, felt "(p++)* = (q++)*" was unclear?

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Michael S@[email protected] to comp.lang.c on Sun Oct 18 18:16:23 2026
    From Newsgroup: comp.lang.c

    On Sun, 18 Oct 2026 16:52:17 +0200
    David Brown <[email protected]> wrote:
    On 18/10/2026 16:13, Michael S wrote:
    On Sun, 18 Oct 2026 14:34:28 +0200
    Janis Papanagnou <[email protected]> wrote:

    On 2026-10-18 14:09, David Brown wrote:

    [...]� (I don't know why N3377 proposed "do { } while NAME ( )"
    rather than "do NAME { } while ( )". )

    Oh! - I can only think that it would then be (sort of) "consistent"
    with the place of the label attacked in a 'while' loop; i.e. behind
    the 'while' keyword. - It's inconsistent in another interpretation,
    though; and I'd certainly have favored the latter form, to have the
    label consistently attached at the loop-entry keyword.

    I'd prefer label consistently attached to the loop-exit keyword. Unfortunately, for() and while() loops have no such keyword.


    That would help for switch inside a loop, or loop inside a switch,
    but do nothing for loop inside a loop or switch inside a switch. I
    don't think anyone involved in the development of the language has
    seriously considered making a solution that only handles the first
    two cases, and not the second two
    Pay attention that 4 patterns are not equal. The second case
    (breaking from loop to outside of containing switch) hardly happens.
    (to say nothing of three or more
    nesting layers). "break_switch" and "break_loop" style solutions have
    been mentioned and quickly dismissed, along with the "break <depth>"
    options.

    It does not look like you understood what I wrote.
    All I wanted to say is that I prefer label to be located at where the
    break goes. Or near this point. Within frame of current C syntax, I
    don't see how to achieve it, except for do-while. But it does not
    change the fact that I find it desirable.
    We'll see what they finally decide (unless it's already clear; I'm
    not sure about the factual weight of the "proposal")...


    I tend to agree with Tim (if I correctly understood him): a.t.m. the
    best outcome would be proposal scrapped completely.


    The proposal has been accepted - it is coming to C and C++, whatever
    you or Tim may think.
    Nothing is set in stone until the standard released. But you are very
    likely right. Which does not make me happier.
    But of course there is no requirement to /use/
    the new feature if you don't like it.
    But others will use it and I'd have to read and understand their code.
    (I don't expect to use it
    significantly myself - I just don't seem to write code in a way that
    could take advantage of it.)

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Michael S@[email protected] to comp.lang.c on Sun Oct 18 18:26:27 2026
    From Newsgroup: comp.lang.c

    On Sun, 18 Oct 2026 16:58:38 +0200
    David Brown <[email protected]> wrote:

    On 18/10/2026 16:24, Michael S wrote:
    On Sun, 18 Oct 2026 13:22:52 +0200
    David Brown <[email protected]> wrote:


    To me, that is just as much gibberish as the original C. No syntax
    is going to make sense of it - no amount of "ref" or "func" or
    pre-fix array notation will help.


    [O.T.]
    Prefix array notation would not. But postfix * notation would,
    somewhat.

    I can agree that notational changes might make it marginally easier
    to understand complex declarations - or mean that declarations could
    be marginally more complex while still being easily understood. But
    nothing can make Bart's exaggerated examples meaningful.

    It would be interesting to find out why designers of C, or of one
    of its ancestors decided that * as prefix is preferable to * as
    postfix. Were they afraid of confusion with usage of * as
    multiplication? Probably not, because confusion can arise about
    equally both for prefix and for postfix.


    I don't know why it is prefix. Maybe they were keen on "*p++ = *q++"
    and similar expressions, felt "(p++)* = (q++)*" was unclear?


    Why would it require parentheses?

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@[email protected] to comp.lang.c on Sun Oct 18 17:49:25 2026
    From Newsgroup: comp.lang.c

    On 2026-10-18 16:13, Michael S wrote:
    On Sun, 18 Oct 2026 14:34:28 +0200
    Janis Papanagnou <[email protected]> wrote:
    On 2026-10-18 14:09, David Brown wrote:

    [...]  (I don't know why N3377 proposed "do { } while NAME ( )"
    rather than "do NAME { } while ( )". )

    Oh! - I can only think that it would then be (sort of) "consistent"
    with the place of the label attacked in a 'while' loop; i.e. behind
    the 'while' keyword. - It's inconsistent in another interpretation,
    though; and I'd certainly have favored the latter form, to have the
    label consistently attached at the loop-entry keyword.

    I'd prefer label consistently attached to the loop-exit keyword.

    I can see that this might look appealing in case of 'break'. In
    case of the same mechanism working also for 'continue' I'd then
    think that it should generally better be an "attribute" of the
    loop entry keyword, i.e. placed where loops start. (But that's
    just my opinion.) Having it at a different place with a do-loop
    I consider a really bad decision. It's advantageous to know the
    direction in which to seek for the label if you inspect code. -
    But okay, it's "C"; I won't heat up about some future C-release
    that I'll never use (especially given that I'm not even be using
    all of those more recent additions that are already available).

    Unfortunately, for() and while() loops have no such keyword.

    Or fortunately. ;-)

    Janis

    [...]

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Sun Oct 18 17:09:04 2026
    From Newsgroup: comp.lang.c

    On 18/10/2026 15:27, David Brown wrote:
    On 18/10/2026 15:33, bart wrote:
    On 18/10/2026 12:22, David Brown wrote:

    To me, that is just as much gibberish as the original C.

    That doesn't matter - the problem is not even knowing what it represents.

    That is, shall we say, a strange attitude.  Gibberish (since that seems
    to be the preferred term here) is gibberish, no matter the language or representation, and is equally meaningless and useless.

    'Gibberish' here refers to the representation, whether the type being described is made-up nonsense or real.

    You may want to know what some complex type is for many reasons, you
    don't necessarily need to understand what it means or why it was used.

    (For example I might come across a type in a C API that I want to
    convert to another language.)


    (That it is an actual function is a surprise. That you can't easily
    tell is crazy.)

    You can tell it very easy from the C - the final bit is parentheses.

    Both actual function declarations and function pointers end in (...).

    Function definitions will have { towards the end of the signature which
    is more of a clue.

    But it is telling that pretty much every language using C-style syntax
    has chosen to use a keyword (fn, fun, func, function or other) to
    introduce a function signature.

    In practice there will be actual types that start to look like
    gibberish, full of *, () and [] that must be in exactly the right place.

    Not in my code, or the code I work with - types are clear to me.  Again, experiences can vary.

    What are you saying here, that your types never involve * () or []? That
    is hard to believe.

      (Of course the syntactical elements must be in
    the right place!)

    Isn't that the problem? C makes it tricky. Here are two very
    straightforward declarations from my projects:

    ref []ichar stringtable # ichar is ref char
    [N]ref proc(T) handlertable

    These are the C versions:

    char *(*stringtable)[];
    void (*handlertable[N)(T);

    They involve * () and [] that must all be in the right place, in the
    right nesting order. In C, parentheses are used to alter precedences as
    well as for parameter lists. This not a thing in LTR forms.

    Additionally, in C, you can sometimes mix up the order of * and [], but
    since a T* value can be indexed, and a T[] value can be dereferenced,
    those errors might still compile.

    So it's a problem. You're saying it isn't one if you do X, Y and Z. I'm
    that you shouldn't need to do X, Y and Z; if you do then it's a
    language problem.


    Use a typedef.  Or since C23, use type inference - that can save naming
    and identifying types when things get complex,

    OK, that's a fifth kind of workaround! Although it is more of an
    unrelated feature.
    This should be simple enough to do in a language without needing to
    follow some back-and-forth algorithm, or use an external tool, or need
    to decompose them into multiple levels using 'typedef', or need to
    disambiguate with parentheses.

    You just /have/ to whine, don't you?  Whenever you complain - usually

    I thought it was, for a change, a civil exchange up to now.

    I'm saying that type syntax should useful without having to resort to
    any of those four workarounds I mentioned.

    If that happens because syntax choices (rather than genuine complexity)
    would otherwise result in gibberish, then that is a failing in the language.


    complicated in C, and someone tells you how it can be handled simply and clearly,

    No. Stuff like this is simple and clear:

    ref proc
    ref func -> void
    * func()void

    Since whatever the type, you can always read off exactly what it is from
    left to right.

    This is gibberish:

    void(*)(void)
    void(*)() (C23)

    unable to simply say "Okay, thanks - that's good to > know" or "Sorry,
    I was wrong, I thought it was hard".  You can't help
    but call things workarounds, or complicated, or get your knickers in a
    twist about having to use a language feature that for some reason you hate.
    This one is universally disliked and even the language creators said it
    was a mistake. I didn't realise that opinion was even controversial.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@[email protected] to comp.lang.c on Sun Oct 18 18:11:18 2026
    From Newsgroup: comp.lang.c

    On 2026-10-18 17:26, Michael S wrote:
    On Sun, 18 Oct 2026 16:58:38 +0200
    David Brown <[email protected]> wrote:
    On 18/10/2026 16:24, Michael S wrote:
    [...]
    It would be interesting to find out why designers of C, or of one
    of its ancestors decided that * as prefix is preferable to * as
    postfix.

    Because it is more "natural" when read, easier to grasp? Simpler
    for compilers? More consistent if all other, especially standard
    operators known from daily use are used in prefix-form (-5, +42,
    !false, ~bitset) in expressions?

    I don't recall to have used any language with infix-expressions
    that would have their monadic operators defined in postfix form.
    The only exception was "C" (and C-oriented languages) with their
    special case of post-increment/post-decrement operators. (Think
    also about the quirk in C++ to define monadic postfix operators
    that require a syntactic dummy type argument). (In low-level RPN
    systems it may appear more "natural", but that just aside.)

    Were they afraid of confusion with usage of * as
    multiplication? Probably not, because confusion can arise about
    equally both for prefix and for postfix.

    I don't know why it is prefix. Maybe they were keen on "*p++ = *q++"
    and similar expressions, felt "(p++)* = (q++)*" was unclear?

    Why would it require parentheses?

    Not necessarily (I think).

    Janis

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Michael S@[email protected] to comp.lang.c on Sun Oct 18 19:32:01 2026
    From Newsgroup: comp.lang.c

    On Sun, 18 Oct 2026 18:11:18 +0200
    Janis Papanagnou <[email protected]> wrote:

    On 2026-10-18 17:26, Michael S wrote:
    On Sun, 18 Oct 2026 16:58:38 +0200
    David Brown <[email protected]> wrote:
    On 18/10/2026 16:24, Michael S wrote:
    [...]
    It would be interesting to find out why designers of C, or of one
    of its ancestors decided that * as prefix is preferable to * as
    postfix.

    Because it is more "natural" when read, easier to grasp?

    IMHO, no.

    Simpler for compilers?

    100% no.

    More consistent if all other, especially standard
    operators known from daily use are used in prefix-form (-5, +42,
    !false, ~bitset) in expressions?

    Unary * is more similar in function to postfix operators like [] and ()
    than to those you mentioned.


    I don't recall to have used any language with infix-expressions
    that would have their monadic operators defined in postfix form.

    I am a Bear of Very Little Brain, and long words Bother Me.

    By chance, did you never use Pascal?

    The only exception was "C" (and C-oriented languages) with their
    special case of post-increment/post-decrement operators. (Think
    also about the quirk in C++ to define monadic postfix operators
    that require a syntactic dummy type argument). (In low-level RPN
    systems it may appear more "natural", but that just aside.)

    Were they afraid of confusion with usage of * as
    multiplication? Probably not, because confusion can arise about
    equally both for prefix and for postfix.

    I don't know why it is prefix. Maybe they were keen on "*p++ =
    *q++" and similar expressions, felt "(p++)* = (q++)*" was unclear?


    Why would it require parentheses?

    Not necessarily (I think).

    Janis



    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Sun Oct 18 18:34:49 2026
    From Newsgroup: comp.lang.c

    On 18/10/2026 15:24, Michael S wrote:
    On Sun, 18 Oct 2026 13:22:52 +0200
    David Brown <[email protected]> wrote:


    To me, that is just as much gibberish as the original C. No syntax
    is going to make sense of it - no amount of "ref" or "func" or
    pre-fix array notation will help.


    [O.T.]
    Prefix array notation would not. But postfix * notation would, somewhat.

    It would be interesting to find out why designers of C, or of one of its ancestors decided that * as prefix is preferable to * as postfix.
    Were they afraid of confusion with usage of * as multiplication?
    Probably not, because confusion can arise about equally both for prefix
    and for postfix.
    With all the other questionable choices, there probably wasn't much
    rationale involved. And there seemed to be little oversight too: other
    people weighing in with their opinions.

    That particular choice had several consequences:

    * If P is a pointer to a struct, then you have to write (*P).m instead
    of P*.m.

    * That led to people using "->" instead (I don't know if that was
    introduced for this reason). But that only works for one level: (**Q).m
    still needs (*Q)->m. With postfix it's tidier and consistent: Q**.m

    * The same when P is a pointer to an array. Pointers to arrays (real
    ones of type (T(*)[] not the T* idiom), are rarely used in C, possibly
    for the reason that indexing would look like (*P)[i], instead of P[i].

    With postfix, it would be the marginally tidier P*[i]. Although here,
    even if unambiguous, the use of "*" looks odd.

    In the event, everybody uses T* for 'array pointers' instead, which is
    less type-safe.

    With function pointer derefs, it would be P*(x) which /is/ ambiguous,
    although for some obscure reason, function pointers don't need to be dereferenced: P(x) would still work.

    * Then we get to type syntax. I think this simplifies a little: * and [] modifiers will always be to the right of a variable. Parentheses for precedence might disappear too. Types will be a little easier to get
    right and to grok.


    When C was created, Pascal with its '^' postfix deref op already
    existed. Although C claims to have some Algol 68 influence (I can't see
    it!) it seems to have ignored Pascal completely.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@[email protected] to comp.lang.c on Sun Oct 18 20:47:13 2026
    From Newsgroup: comp.lang.c

    On 18/10/2026 17:16, Michael S wrote:
    On Sun, 18 Oct 2026 16:52:17 +0200
    David Brown <[email protected]> wrote:

    On 18/10/2026 16:13, Michael S wrote:
    On Sun, 18 Oct 2026 14:34:28 +0200
    Janis Papanagnou <[email protected]> wrote:

    On 2026-10-18 14:09, David Brown wrote:

    [...]  (I don't know why N3377 proposed "do { } while NAME ( )"
    rather than "do NAME { } while ( )". )

    Oh! - I can only think that it would then be (sort of) "consistent"
    with the place of the label attacked in a 'while' loop; i.e. behind
    the 'while' keyword. - It's inconsistent in another interpretation,
    though; and I'd certainly have favored the latter form, to have the
    label consistently attached at the loop-entry keyword.

    I'd prefer label consistently attached to the loop-exit keyword.
    Unfortunately, for() and while() loops have no such keyword.


    That would help for switch inside a loop, or loop inside a switch,
    but do nothing for loop inside a loop or switch inside a switch. I
    don't think anyone involved in the development of the language has
    seriously considered making a solution that only handles the first
    two cases, and not the second two

    Pay attention that 4 patterns are not equal. The second case
    (breaking from loop to outside of containing switch) hardly happens.


    I know they are not equal - that's why I wrote all four combinations.
    But I have no good statistics to determine which combinations might be
    more common than others for wanting to break out of the outer structure.
    I know /you/ said that /you/ regularly want to break out of a switch
    that is inside a loop - fair enough. It is not something that I have
    needed to do, or at least not often enough to bother about it. Indeed,
    none of the cases are particularly common in my code. I've no doubt
    come across some of them at times, and dealt with them using extra bools
    or splitting up big functions into smaller ones where "return" could do
    the job. Certainly I do not ever remember wishing I had a "break_loop" statement, or a labelled break.

    But the C standards committee don't care about my code. They don't care
    about your code either. They care about what they think makes a
    difference to large numbers of C programmers. I can't tell you if they
    have access to good statistics, or are using the combined gut feelings
    of the committee members. However, it would strike me as a serious
    wasted opportunity if they made an addition to the language that only
    handled the one pattern that you find most common in your code, rather
    than also making it work for the other patterns.

    (to say nothing of three or more
    nesting layers). "break_switch" and "break_loop" style solutions have
    been mentioned and quickly dismissed, along with the "break <depth>"
    options.


    It does not look like you understood what I wrote.
    All I wanted to say is that I prefer label to be located at where the
    break goes.

    In C2y, you /do/ put the label along with the break - you write "break outer;". But you also have to put the label "outer : " at the start of
    the control structure.

    If you want to have some kind of "break to outer structure" /without/
    having a name or label on the structure, then you need some other way to
    refer to it. I thought you had said before your preference was for
    something like "break_switch" (ignoring any bike-shedding on the
    syntax), which would work in the particular case of a switch with nested loop(s). And as I wrote, this was considered and dismissed. (Equally,
    the other plausible syntax that does not require an explicit label -
    "break <depth>", was considered and dismissed.)

    Or near this point. Within frame of current C syntax, I
    don't see how to achieve it, except for do-while. But it does not
    change the fact that I find it desirable.


    Am I right in thinking you would then have :

    do {
    switch (...) {
    break outer;
    while outer (...);

    You are happy with labelling the loop or switch, but want the label at
    the end, not the start?

    Why not then just use "goto" and put a label at the end of the loop or
    switch? (This is allowed in C23.)

    We'll see what they finally decide (unless it's already clear; I'm
    not sure about the factual weight of the "proposal")...


    I tend to agree with Tim (if I correctly understood him): a.t.m. the
    best outcome would be proposal scrapped completely.


    The proposal has been accepted - it is coming to C and C++, whatever
    you or Tim may think.

    Nothing is set in stone until the standard released. But you are very
    likely right. Which does not make me happier.


    Okay. There are always changes that we like, changes we dislike, and
    (often the majority) changes to which we are indifferent.

    But of course there is no requirement to /use/
    the new feature if you don't like it.

    But others will use it and I'd have to read and understand their code.


    True - but do you /really/ think that is going to be a problem?

    (I don't expect to use it
    significantly myself - I just don't seem to write code in a way that
    could take advantage of it.)






    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@[email protected] to comp.lang.c on Sun Oct 18 21:09:17 2026
    From Newsgroup: comp.lang.c

    On 18/10/2026 18:09, bart wrote:
    On 18/10/2026 15:27, David Brown wrote:
    On 18/10/2026 15:33, bart wrote:
    On 18/10/2026 12:22, David Brown wrote:

    To me, that is just as much gibberish as the original C.

    That doesn't matter - the problem is not even knowing what it
    represents.

    That is, shall we say, a strange attitude.  Gibberish (since that
    seems to be the preferred term here) is gibberish, no matter the
    language or representation, and is equally meaningless and useless.

    'Gibberish' here refers to the representation, whether the type being described is made-up nonsense or real.


    Maybe that's what /you/ mean by it, but to me the type itself there is gibberish - no matter what representation you use.

    You may want to know what some complex type is for many reasons, you
    don't necessarily need to understand what it means or why it was used.

    (For example I might come across a type in a C API that I want to
    convert to another language.)

    You are just making stuff up. C API's use different named types just
    like any other C code, so that people can understand what they are.


    In practice there will be actual types that start to look like
    gibberish, full of *, () and [] that must be in exactly the right place.

    Not in my code, or the code I work with - types are clear to me.
    Again, experiences can vary.

    What are you saying here, that your types never involve * () or []? That
    is hard to believe.

    I'll cross off "false dichotomy" on my "Bart's logical fallacies" bingo
    card for the day.

    I don't write types that look like gibberish, full of *, () and [].
    That does not mean I do not write types that contain *, () or [].


      (Of course the syntactical elements must be in the right place!)

    Isn't that the problem? C makes it tricky. Here are two very
    straightforward declarations from my projects:

      ref []ichar stringtable               # ichar is ref char
      [N]ref proc(T) handlertable

    Are you suggesting that in your language, "stringtable" could also be
    declared as :

    ref ichar [stringtable]
    or
    ][ stringtable ichar ref
    ?

    I suspect that your language also requires the syntactical elements to
    be in the right place.



    These are the C versions:

      char *(*stringtable)[];
      void (*handlertable[N)(T);

    They involve * () and [] that must all be in the right place, in the
    right nesting order. In C, parentheses are used to alter precedences as
    well as for parameter lists. This not a thing in LTR forms.

    I assume that :

    [N] ref proc(T) handlertable

    and

    ref [N] proc(T) handlertable

    are different?

    You need to give things in the right order, or use parentheses, to get
    the right "type expression". It's just like any other kind of expression.

    The intention of the declaration syntax in C is that the declaration
    order follows usage. If you would not write code that /uses/ a
    declaration in a particular way - like so many *, () and [] sets that it
    is hard to comprehend - then do not write /declarations/ in that way.

    I don't think there is anything inherently better about C's declaration
    syntax than your declaration syntax, or others that are more
    right-to-left or more left-to-right. There's a lot of good things to
    say about left-to-right ordering, since that is the order for reading
    (in English, anyway). But it also means the declaration order and usage
    order are different unless your array subscript, pointer dereference and
    call operators are also all left-to-right. My point is not that C's
    syntax is wonderful (I disagree with Kenny here), but that it works fine
    in practice, you don't have to write incomprehensible declarations, and
    that if you /do/ want to write incomprehensible declarations, you can do
    it in any language just as easily.


    Additionally, in C, you can sometimes mix up the order of * and [], but since a T* value can be indexed, and a T[] value can be dereferenced,
    those errors might still compile.

    So it's a problem. You're saying it isn't one if you do X, Y and Z. I'm
     that you shouldn't need to do X, Y and Z; if you do then it's a
    language problem.


    I know you say that - you are wrong to say that.

    If you want good, clear, correct C code, you need to write good, clear, correct C code. That's the X, Y and Z. And that applies to all
    languages, including yours. The details may differ, but the principles
    do not.

    You can well hold the opinion that you personally find it easier to
    write good, clear, correct code in your own language than you do in C.
    It would indeed be extraordinary if that were not the case. But your
    opinion there does not make it fact, or mean it applies to others.


    Use a typedef.  Or since C23, use type inference - that can save
    naming and identifying types when things get complex,

    OK, that's a fifth kind of workaround! Although it is more of an
    unrelated feature.
    This should be simple enough to do in a language without needing to
    follow some back-and-forth algorithm, or use an external tool, or
    need to decompose them into multiple levels using 'typedef', or need
    to disambiguate with parentheses.

    You just /have/ to whine, don't you?  Whenever you complain - usually

    I thought it was, for a change, a civil exchange up to now.

    It was - I really am trying, but you wrote one knee-jerk comment too
    many. I will try to reset.



    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@[email protected] to comp.lang.c on Sun Oct 18 21:11:19 2026
    From Newsgroup: comp.lang.c

    On 18/10/2026 17:26, Michael S wrote:
    On Sun, 18 Oct 2026 16:58:38 +0200
    David Brown <[email protected]> wrote:

    On 18/10/2026 16:24, Michael S wrote:
    On Sun, 18 Oct 2026 13:22:52 +0200
    David Brown <[email protected]> wrote:


    To me, that is just as much gibberish as the original C. No syntax
    is going to make sense of it - no amount of "ref" or "func" or
    pre-fix array notation will help.


    [O.T.]
    Prefix array notation would not. But postfix * notation would,
    somewhat.

    I can agree that notational changes might make it marginally easier
    to understand complex declarations - or mean that declarations could
    be marginally more complex while still being easily understood. But
    nothing can make Bart's exaggerated examples meaningful.

    It would be interesting to find out why designers of C, or of one
    of its ancestors decided that * as prefix is preferable to * as
    postfix. Were they afraid of confusion with usage of * as
    multiplication? Probably not, because confusion can arise about
    equally both for prefix and for postfix.


    I don't know why it is prefix. Maybe they were keen on "*p++ = *q++"
    and similar expressions, felt "(p++)* = (q++)*" was unclear?


    Why would it require parentheses?


    Maybe it would not - but I think perhaps "p++* = q++*" would be even
    less clear. But again, I have no idea here, and if dereferencing had
    been postfix, it might have had knock-on effects to other aspects of
    operator ordering or precedence.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Michael S@[email protected] to comp.lang.c on Sun Oct 18 22:38:59 2026
    From Newsgroup: comp.lang.c

    On Sun, 18 Oct 2026 20:47:13 +0200
    David Brown <[email protected]> wrote:
    On 18/10/2026 17:16, Michael S wrote:
    On Sun, 18 Oct 2026 16:52:17 +0200
    David Brown <[email protected]> wrote:

    On 18/10/2026 16:13, Michael S wrote:
    On Sun, 18 Oct 2026 14:34:28 +0200
    Janis Papanagnou <[email protected]> wrote:

    On 2026-10-18 14:09, David Brown wrote:

    [...]� (I don't know why N3377 proposed "do { } while NAME ( )"
    rather than "do NAME { } while ( )". )

    Oh! - I can only think that it would then be (sort of)
    "consistent" with the place of the label attacked in a 'while'
    loop; i.e. behind the 'while' keyword. - It's inconsistent in
    another interpretation, though; and I'd certainly have favored
    the latter form, to have the label consistently attached at the
    loop-entry keyword.

    I'd prefer label consistently attached to the loop-exit keyword.
    Unfortunately, for() and while() loops have no such keyword.


    That would help for switch inside a loop, or loop inside a switch,
    but do nothing for loop inside a loop or switch inside a switch. I
    don't think anyone involved in the development of the language has
    seriously considered making a solution that only handles the first
    two cases, and not the second two

    Pay attention that 4 patterns are not equal. The second case
    (breaking from loop to outside of containing switch) hardly happens.


    I know they are not equal - that's why I wrote all four combinations.
    But I have no good statistics to determine which combinations might
    be more common than others for wanting to break out of the outer
    structure. I know /you/ said that /you/ regularly want to break out
    of a switch that is inside a loop - fair enough. It is not something
    that I have needed to do, or at least not often enough to bother
    about it. Indeed, none of the cases are particularly common in my
    code. I've no doubt come across some of them at times, and dealt
    with them using extra bools or splitting up big functions into
    smaller ones where "return" could do the job. Certainly I do not
    ever remember wishing I had a "break_loop" statement, or a labelled
    break.

    But the C standards committee don't care about my code. They don't
    care about your code either. They care about what they think makes a difference to large numbers of C programmers. I can't tell you if
    they have access to good statistics, or are using the combined gut
    feelings of the committee members. However, it would strike me as a
    serious wasted opportunity if they made an addition to the language
    that only handled the one pattern that you find most common in your
    code, rather than also making it work for the other patterns.

    (to say nothing of three or more
    nesting layers). "break_switch" and "break_loop" style solutions
    have been mentioned and quickly dismissed, along with the "break
    <depth>" options.


    It does not look like you understood what I wrote.
    All I wanted to say is that I prefer label to be located at where
    the break goes.

    In C2y, you /do/ put the label along with the break - you write
    "break outer;". But you also have to put the label "outer : " at the
    start of the control structure.

    If you want to have some kind of "break to outer structure" /without/
    having a name or label on the structure, then you need some other way
    to refer to it. I thought you had said before your preference was
    for something like "break_switch" (ignoring any bike-shedding on the syntax), which would work in the particular case of a switch with
    nested loop(s). And as I wrote, this was considered and dismissed.
    (Equally, the other plausible syntax that does not require an
    explicit label - "break <depth>", was considered and dismissed.)

    Or near this point. Within frame of current C syntax, I
    don't see how to achieve it, except for do-while. But it does not
    change the fact that I find it desirable.


    Am I right in thinking you would then have :

    do {
    switch (...) {
    break outer;
    while outer (...);

    You are happy with labelling the loop or switch, but want the label
    at the end, not the start?

    Almost. I want it at the end and I want it with syntax that can't be
    confused with regular goto targets.
    Why not then just use "goto" and put a label at the end of the loop
    or switch? (This is allowed in C23.)

    Like just about everybody else, I prefer weaker control transfers. They
    are not easier to write, but easier to follow by reader.
    goto is too powerful - can go everywhere within function. That part is
    improved by C2y proposal.
    But the labels that goto targets are also too powerful - they can be
    reached from everywhere in the function. That part is not just not
    improved by proposal, but made worse, because now we not just have a
    too powerful label (that we have to name, which is problem by itself,
    but lesser evil than break N alternative), but this label creates
    another, completely unnecessary, target for goto, that the reader of
    code should have in mind.
    We'll see what they finally decide (unless it's already clear;
    I'm not sure about the factual weight of the "proposal")...


    I tend to agree with Tim (if I correctly understood him): a.t.m.
    the best outcome would be proposal scrapped completely.


    The proposal has been accepted - it is coming to C and C++,
    whatever you or Tim may think.

    Nothing is set in stone until the standard released. But you are
    very likely right. Which does not make me happier.


    Okay. There are always changes that we like, changes we dislike, and
    (often the majority) changes to which we are indifferent.

    But of course there is no requirement to /use/
    the new feature if you don't like it.

    But others will use it and I'd have to read and understand their
    code.

    True - but do you /really/ think that is going to be a problem?

    For me, personally? May be not. Due to (or because of) my age, with
    retirement not too distant.
    (I don't expect to use it
    significantly myself - I just don't seem to write code in a way
    that could take advantage of it.)






    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@[email protected] (Dan Cross) to comp.lang.c on Sun Oct 18 22:18:59 2026
    From Newsgroup: comp.lang.c

    In article <11b2pq5$3pvda$[email protected]>,
    Janis Papanagnou <[email protected]> wrote:
    On 2026-10-18 16:13, Michael S wrote:
    On Sun, 18 Oct 2026 14:34:28 +0200
    Janis Papanagnou <[email protected]> wrote:
    On 2026-10-18 14:09, David Brown wrote:

    [...]  (I don't know why N3377 proposed "do { } while NAME ( )"
    rather than "do NAME { } while ( )". )

    Oh! - I can only think that it would then be (sort of) "consistent"
    with the place of the label attacked in a 'while' loop; i.e. behind
    the 'while' keyword. - It's inconsistent in another interpretation,
    though; and I'd certainly have favored the latter form, to have the
    label consistently attached at the loop-entry keyword.

    I'd prefer label consistently attached to the loop-exit keyword.

    I can see that this might look appealing in case of 'break'. In
    case of the same mechanism working also for 'continue' I'd then
    think that it should generally better be an "attribute" of the
    loop entry keyword, i.e. placed where loops start. (But that's
    just my opinion.) Having it at a different place with a do-loop
    I consider a really bad decision. It's advantageous to know the
    direction in which to seek for the label if you inspect code. -
    But okay, it's "C"; I won't heat up about some future C-release
    that I'll never use (especially given that I'm not even be using
    all of those more recent additions that are already available).

    I think colocating it with `do` might create a syntactic
    ambiguity. In the case of `for`, `while`, and `select`, there
    is a required token following the keyword (the `(`). However,
    for a `do`/`while` loop, `do` is followed immediately by a,
    `secondary-block` production. In particular, you do not _need_
    braces to denote a compound statement after `do`; something like
    `do i++; while (i < j);` is perfectly legal in C.

    In the N3377 proposal, the new `block-name` is just an
    identifier. If it were allowed immediately after the `do`, then
    given, `do NAME statement; while(condition);` you can't tell
    `NAME` from the name of the loop and a random identifier before
    a statement; something like `do LOOP i++; while (i < j);`
    appears as though it _would_ be be syntactically valid by N3377
    as presently worked, but is the programmer's intent to create a
    loop name, or should this just be a syntax error?

    By requiring the block-name between a keyword and a
    syntactically required `(`, you remove that ambiguity: if there
    is an identifier there, then it is a `block-name`; if not, then
    the block has no name.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Sun Oct 18 23:20:31 2026
    From Newsgroup: comp.lang.c

    On 18/10/2026 20:09, David Brown wrote:
    On 18/10/2026 18:09, bart wrote:

    Isn't that the problem? C makes it tricky. Here are two very
    straightforward declarations from my projects:

       ref []ichar stringtable               # ichar is ref char >>    [N]ref proc(T) handlertable

    Are you suggesting that in your language, "stringtable" could also be declared as :

        ref ichar [stringtable]
    or
        ][ stringtable ichar ref
    ?

    (Warning: longer post than I'd intended.)

    I think you're clutching at straws.

    [] or [N] means 'array of'

    ref means 'pointer to'

    proc means 'function returning void'

    Then there is an existing standard or user type T.

    You use these building blocks to construct types of any complexity. They
    are simply chained together, from left to right, ending with T at the right.

    If this is part of a variable declaration, then names follow on the
    right (but syntaxes vary here).

    So you know that ][ makes no sense. Neither does [stringtable] unless 'stringtable' is a valid array-bound expression.

    Example, I want a 'pointer to an array of pointer to int':

    pointer to array of pointer to int English and CDECL
    ref [] ref int My syntax

    So 'ref [] ref int'. Now I want to declare 3 such variables of the same
    type; no problem:

    ref [] ref int x, y, z

    Now let's try the same exercise with C:

    'pointer to' is *
    'array of' is []

    But how TF do they go together? Where do I start? It seems I may have to
    start from the other end:

    int

    Now I add the pointer:

    int *

    I know this far! Now I need to apply [] somewhere, and then another *,
    but this can't be it:

    int *[]*

    OK, here's one I prepared earlier (I didn't need CDECL at all...):

    int *(*)[]

    Now how about my three variables? Well, here's where the first goes, and
    CDECL agrees with me:

    int *(*x)[]

    But what about y and z? It seems that, in C, the parts of typespec other
    than the final T can't be shared. So it has to be this:

    int *(*x)[], *(*y)[], *(z)[];

    OK, obviously I lied; I had to use CDECL even for a fairly simple type, because I find C type syntax utterly impossible.

    I suspect that your language also requires the syntactical elements to
    be in the right place.

    The difference is that that is literally as simple as writing ABC. This
    is the example above:

    pointer to array of pointer to int x
    ref [] ref int x

    A B C D E

    The C version is:

    int *(* x)[]

    D C A E B

    Well it's either C A or A C; I don't know, and I don't care as
    thankfully I'm not going to deal with this godforsaken language any more.

    I assume that :

        [N] ref proc(T) handlertable

    and

        ref [N] proc(T) handlertable

    are different?

    Start on the left. One is an array, the other a pointer (to an array of functions so it's not valid).

    You need to give things in the right order, or use parentheses, to get
    the right "type expression"  It's just like any other kind of expression.

    So, what do you think the purpose of CDECL is? Since to you, NOTHING
    about C type syntax ever appears to be a problem.

    Try explaining to me in English what either of those two types are.
    You're going to describe them in left-to-right order just like CDECL.

    This is also how I would think of them. Then my syntax merely
    transcribes that exactly: I can write it as fast as I can type and I
    will be 100% sure it corresponds to the type I want.

    Try reading a C type spec out loud in the order it is in source code,
    complete with parentheses. It just does not work!

    The intention of the declaration syntax in C is that the declaration
    order follows usage.

    Which doesn't work either. If I declare P to be a pointer to int, then
    it will likely be used like this in an expression:

    P

    I might also write &P, or *P, or P[i], or *(P + i). With a more complex
    type I might also partially dereference or index it.

    Now tell me that the declaration of a struct also follows its usage!



    There's a lot of good things to say about
    left-to-right ordering, since that is the order for reading (in English, anyway).  But it also means the declaration order and usage order are different unless your array subscript, pointer dereference and call operators are also all left-to-right.

    Is that important? People don't seem to have a problem writing
    expressions in any language, other than quibbles about post- and pre-fix operators.

    But why is it necessary for the shape of a declaration to have anything
    to do with what happens in an expression? I've showed that that can vary anyway, and with some things (such as structs) it is meaningless.

    It simply does not work in C, and just leads to confusion:

    int a;
    int
    *p = &a;
    *p = a;

    The LHSs of those last two lines are the same, but the RHSs must be
    different. One of them is being dereferenced, and the other isn't, even
    those both /look/ as though they dereference p.

    NO DEREFERENCING is done in the declaration, but it uses dereference
    syntax in something that looks exactly like an assignment.

    Just admit that the whole concept was a failure. The creators have
    already done so.

      My point is not that C's syntax
    is wonderful (I disagree with Kenny here),

    He was probably being sarcastic.


    but that it works fine in
    practice,

    It works in practice with a lot of trouble, but it is not fine.

    you don't have to write incomprehensible declarations

    My threshold is lower than yours. Just mix one * and one [], and I'm
    already lost.

    That you need to disambiguate using () to distingish *[] from (*)[] is
    the wrong approach. That changes between pointer/array and
    array/pointer, but mysteriously the * and [] stay in the same order?

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@[email protected] (Dan Cross) to comp.lang.c on Sun Oct 18 22:33:28 2026
    From Newsgroup: comp.lang.c

    In article <11b285v$121v2$[email protected]>,
    David Brown <[email protected]> wrote:
    On 17/10/2026 01:29, Janis Papanagnou wrote:
    On 2026-10-17 00:00, Keith Thompson wrote:
    Tim Rentsch <[email protected]> writes:
    Keith Thompson <[email protected]> writes:
    [...]
    There's a proposal for C2y to use goto labels as loop names, and a
    competing one to define a new syntax like "for NAME (;;)" :
    [...]

    I'm not particularly a fan of multi-level break/continue.  But if
    we're going to have one of these, the second ("for NAME (;;)") is
    unquestionably better.

    Unquestionably?  Why?

    Why would one question an opinion? ;-)

    Time didn't word it as a personal opinion - he made it clear that he
    doesn't think anyone else could have a different opinion.

    Tim often makes it sound as though he believes that his opinions
    are facts.

    As far as I recall, in "C", the name of the function was often put
    separately (first in the line) to have an easy method to find its
    declaration by simple "grep ^fname". (With any sophisticated editor
    this might be a weak argument, though.)

    I think it was popularised with a shortcut in emacs.

    No, it was `grep`. The convention originated on Unix, but well
    before there was a version of Emacs in widespread use on those
    systems; most Unix programmers were using `ed` at the time, and
    `vi` was still a few years away; `ctags` was not a thing yet.

    Recall that early versions of C defaulted to `int` as a return
    type if otherwise unspecified; there was no `void`, so if a
    programmer had no intention of returning anything at all, they
    would just omit the return type and the `return` statement. The
    result was that there were many functions that declared no
    return type, and just started with the function at the beginning
    of the line; it was natural to use `grep ^name` to look for
    those, and it was sufficiently useful that the convention stuck
    even as we gained both more powerful editors and more stricter
    versions of C.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From antispam@[email protected] (Waldek Hebisch) to comp.lang.c on Sun Oct 18 23:51:25 2026
    From Newsgroup: comp.lang.c

    Dan Cross <[email protected]> wrote:
    In article <11b2pq5$3pvda$[email protected]>,
    Janis Papanagnou <[email protected]> wrote:
    On 2026-10-18 16:13, Michael S wrote:
    On Sun, 18 Oct 2026 14:34:28 +0200
    Janis Papanagnou <[email protected]> wrote:
    On 2026-10-18 14:09, David Brown wrote:

    [...]  (I don't know why N3377 proposed "do { } while NAME ( )"
    rather than "do NAME { } while ( )". )

    Oh! - I can only think that it would then be (sort of) "consistent"
    with the place of the label attacked in a 'while' loop; i.e. behind
    the 'while' keyword. - It's inconsistent in another interpretation,
    though; and I'd certainly have favored the latter form, to have the
    label consistently attached at the loop-entry keyword.

    I'd prefer label consistently attached to the loop-exit keyword.

    I can see that this might look appealing in case of 'break'. In
    case of the same mechanism working also for 'continue' I'd then
    think that it should generally better be an "attribute" of the
    loop entry keyword, i.e. placed where loops start. (But that's
    just my opinion.) Having it at a different place with a do-loop
    I consider a really bad decision. It's advantageous to know the
    direction in which to seek for the label if you inspect code. -
    But okay, it's "C"; I won't heat up about some future C-release
    that I'll never use (especially given that I'm not even be using
    all of those more recent additions that are already available).

    I think colocating it with `do` might create a syntactic
    ambiguity. In the case of `for`, `while`, and `select`, there
    is a required token following the keyword (the `(`). However,
    for a `do`/`while` loop, `do` is followed immediately by a,
    `secondary-block` production. In particular, you do not _need_
    braces to denote a compound statement after `do`; something like
    `do i++; while (i < j);` is perfectly legal in C.

    In the N3377 proposal, the new `block-name` is just an
    identifier. If it were allowed immediately after the `do`, then
    given, `do NAME statement; while(condition);` you can't tell
    `NAME` from the name of the loop and a random identifier before
    a statement; something like `do LOOP i++; while (i < j);`
    appears as though it _would_ be be syntactically valid by N3377
    as presently worked, but is the programmer's intent to create a
    loop name, or should this just be a syntax error?

    By requiring the block-name between a keyword and a
    syntactically required `(`, you remove that ambiguity: if there
    is an identifier there, then it is a `block-name`; if not, then
    the block has no name.

    AFAICS this is worse, both:

    do (i++); while (i < j);

    and

    do LOOP(i++); while (i < j);

    are currently legal (assuming that 'LOOP' is a function).

    Writing statement with parentheses may look silly, but such code
    may be easily produced due to use of macros.
    --
    Waldek Hebisch
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@[email protected] (Dan Cross) to comp.lang.c on Sun Oct 18 23:56:47 2026
    From Newsgroup: comp.lang.c

    In article <11b3gkj$mt2$[email protected]>,
    Dan Cross <[email protected]> wrote:
    In article <11b2pq5$3pvda$[email protected]>,
    Janis Papanagnou <[email protected]> wrote:
    On 2026-10-18 16:13, Michael S wrote:
    On Sun, 18 Oct 2026 14:34:28 +0200
    Janis Papanagnou <[email protected]> wrote:
    On 2026-10-18 14:09, David Brown wrote:

    [...]  (I don't know why N3377 proposed "do { } while NAME ( )"
    rather than "do NAME { } while ( )". )

    Oh! - I can only think that it would then be (sort of) "consistent"
    with the place of the label attacked in a 'while' loop; i.e. behind
    the 'while' keyword. - It's inconsistent in another interpretation,
    though; and I'd certainly have favored the latter form, to have the
    label consistently attached at the loop-entry keyword.

    I'd prefer label consistently attached to the loop-exit keyword.

    I can see that this might look appealing in case of 'break'. In
    case of the same mechanism working also for 'continue' I'd then
    think that it should generally better be an "attribute" of the
    loop entry keyword, i.e. placed where loops start. (But that's
    just my opinion.) Having it at a different place with a do-loop
    I consider a really bad decision. It's advantageous to know the
    direction in which to seek for the label if you inspect code. -
    But okay, it's "C"; I won't heat up about some future C-release
    that I'll never use (especially given that I'm not even be using
    all of those more recent additions that are already available).

    I think colocating it with `do` might create a syntactic
    ambiguity. In the case of `for`, `while`, and `select`, there
    is a required token following the keyword (the `(`). However,
    for a `do`/`while` loop, `do` is followed immediately by a,
    `secondary-block` production. In particular, you do not _need_
    braces to denote a compound statement after `do`; something like
    `do i++; while (i < j);` is perfectly legal in C.

    Rather, you _would_ need braces for a _compound statement_, but
    a compound statement is not required here.

    In the N3377 proposal, the new `block-name` is just an
    identifier. If it were allowed immediately after the `do`, then
    given, `do NAME statement; while(condition);` you can't tell
    `NAME` from the name of the loop and a random identifier before
    a statement; something like `do LOOP i++; while (i < j);`
    appears as though it _would_ be be syntactically valid by N3377
    as presently worked, but is the programmer's intent to create a
    loop name, or should this just be a syntax error?

    By requiring the block-name between a keyword and a
    syntactically required `(`, you remove that ambiguity: if there
    is an identifier there, then it is a `block-name`; if not, then
    the block has no name.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@[email protected] (Dan Cross) to comp.lang.c on Mon Oct 19 01:19:29 2026
    From Newsgroup: comp.lang.c

    In article <11b0mfv$j5ll$[email protected]>, bart <[email protected]> wrote:
    On 17/10/2026 18:58, Dan Cross wrote:
    In article <11avmfb$55rt$[email protected]>, bart <[email protected]> wrote:
    On 17/10/2026 04:19, Dan Cross wrote:
    In article <11auad0$3no1k$[email protected]>, bart <[email protected]> wrote: >>>>> Those are considered more productive.

    ...and you think that's because of the syntax, and not the high
    level nature of those languages?

    It's a combination.

    Riiiight.

    So greatly simplifying syntax, all other things being equal, does not >increase productivity at all? Gotcha.

    Logical fallacy. I didn't say it did not; I said the languages
    you pointed out as being "more productive" than C had other
    attributes that make them more productive that you ignored in
    your fervor to focus solely on syntax.

    I see that you convenient snipped out my comment about C++,
    which is the direct counter example. C++ shares much syntax
    with C, but also has attributes that make it (generally) more
    productive than C; for example, a broad standard library of
    generic types and a useful `std::string` type.

    Go and Rust both similarly share lots of syntactic elements with
    C, yet both are also broadly more "productive".

    Yes. C's declaration syntax is famously abstruse; film at 11.

    And ... that's it? Just accept it? How about doing something about it!

    One time, shortly before I deployed to Afghanistan, my (then)
    girlfriend and I were sleeping in my apartment in the far
    northern reaches of Manhattan when a very (VERY) loud party
    started blaring music outside; it was about 1am, and it woke us
    both up. "Well, aren't you going to _do_ something about it?"
    she asked me, to which I replied, "what, exactly, would you like
    me to do?"

    I survived that deployment, but the relationship did not.

    I'm angry because to me C was so unusable that I had to create and
    maintain my own products over decades.

    "Had" is a strong word; dare I say it...a subjective word.

    In fact, there have been all kinds of alternatives for years.
    In the earlish 1980s, there was Modula-2, PL/M, Forth, Ada, CLU,
    BLISS, and so on. You yourself admit you started from Algol68.
    By the late 1980s you had Oberon, decent versions of ML, C++
    and Objective-C, etc; by the 1990s, there were more than you
    could shake a stick at. Now? Take your pick.

    You never "had" to use your own language.

    Then I later found that C had insinuated itself into every API and every >open source product I wanted to use. Even ABIs, supposedly
    language-neutral, pay deference to it. Even as a compiler target, there
    was no other choice.

    So I ended having to deal with it anyway, but thankfully avoided have to >write it.

    See my earlier post. That ecosystem is one of the things that
    makes C _useful_. /eyeroll

    If C had used LTR type syntax and somebody
    proposed using inside-out back-and-forth syntax like 'void(*)(void)',
    they'd think they were having a laugh, as it would be ridiculous.

    Unknowable.

    You do know; you just don't want to admit it. (Imagine introducing C >declarations into a current language.)

    No, really; C's declaration syntax was inspired by FORTRAN, and
    generations of scientists and engineers have managed that
    language just fine. Generations of programmers have handled C's
    all right as well.

    Then your point is minor at best. Here's a thought experiment:
    suppose I suddenly came to my senses and agreed with everything
    you say: I'm willing to totally toss out C and adopt Bart's
    language yesterday.

    THIS IS NOT ABOUT MY LANGUAGE!

    Then why do you keep bringing your language up, showing snippets
    of its syntax, and so on?

    Why hasn't there long been an alternative systems language that didn't
    have C's crazy syntax and stupid quirks? I mean like 30-50 years ago.

    There...have been? And still are?

    Yes, mine has lots of examples of how some alternative features could
    work; so what? I am not selling my language.

    Oh good, so you'll stop bringing it up?

    Where do I get a compiler? What learning
    resources exist? Oh, and I need it to generate code for an
    ARM Cortex-M0 part; does it do that? I also need RV64GC and
    x86_64 and probably aarch64, too. Might want to throw in
    Xtensa while we're at it: does your compiler do all of that?
    What if I need a debugger? Oh, and I need to use crypto
    libraries that are supplied from a vendor; they use the C ABI.
    What's the inter-op story like?

    My language was for in-house use; it was never intended as a product.

    (If you really want to try it, I can supply an ASM file for you to
    build, but it works on Windows. I can no longer supply a transpiled C >version that part work on Linux;

    Not really, no. I don't do Windows, and I have no desire to
    waste my time mucking about with random assembler to get it to
    run on something I do have.

    But this sort of thing is exactly what I'm talking about: your
    language is not useful beyond a userbase of one. You solved a
    set of "problems" that you defined for yourself, whether they
    were real or not, and now are now sitting here trying to use
    that as evidence about a general argument based on false
    premises ("there was no alternative! I _had_ to do my own
    thing!" "Oh, can I look at it?" "Oh, no; it only works for me,
    on my laptop." "....").

    I have destroyed my C-related projects.)

    Uh, ok.

    The C API (not ABI) point is valid, and another bugbear. Why can't APIs
    be expressed in a language-agnostic manner? This would help other
    languages that also need to solve the problem of creating bindings to >libraries that primarily use a C API.

    In fact, there have been efforts to do this for _years_. From
    heavy weight IDLs and ORBs to wrappers like `swig`, and all of
    the languages that used common ABIs (like the VAX Calling
    Standard). They all suffer from one of two primary categories
    of problems: a) either the mechanisms are too heavyweight or
    cumbersome for easy use, or b) the semantics of languages vary
    far too much between languages, so even if you can do something
    simple like define compatible data types, language A may not be
    able to meet all the constraints imposed by language B.

    C is a terrible choice for a cross-language API, as too many C-isms
    creep in (like C macros, or vaguely defined types, including the famous >'plain char' that exists in no other language, which is neither signed
    nor unsigned, and above all C preprocessor features).

    That's why ABIs matter.

    Look at the Vax-11 Procedure Calling and Condition Handling
    Standard from VMS 2.0; they simply wrote down what this stuff
    meant, and you could call between essentially any language on
    that system, whether it was C, Fortran, Bliss, COBOL, or
    whatever.

    Good for you. Totally irrelevant to the history of C.

    It means that meagre hardware resources don't have to compromise the
    design of a language, especially when it comes to syntax.

    So you can't use limited resources as an excuse for its questionable >choices. Actually some choices actually made it harder to parse.

    The team that created C was familiar with, and rather liked,
    Richard Martin's BCPL. B was created as sort of a chopped down
    BCPL that could fit on the PDP-7, a machine with 4KW of 18-bit
    core memory, at an access time of ~1.5ms, where most
    instructions touch memory twice. Oh, and that machine was
    running a multitasking, multiuser operating system and was
    self-hosting. And you are seriously comparing your single-user
    home PC with 64k of RAM to that environment? I'm not sure you
    know what "hardware limitations" are.

    As mentioned, C came from B, once they got a PDP-11; it was an
    incremental evolution of a language they already had. The type
    syntax you find so distasteful was inspired by FORTRAN.

    It's so weird to me that you make such absolute pronouncements
    about C and the choices that into its design, but are so
    ajbectly ignorant of the actual history. Bluntly, you just are
    not very well informed about it to make cogent comments.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@[email protected] to comp.lang.c on Sun Oct 18 18:33:19 2026
    From Newsgroup: comp.lang.c

    Michael S <[email protected]> writes:
    On Sun, 18 Oct 2026 14:34:28 +0200
    Janis Papanagnou <[email protected]> wrote:
    On 2026-10-18 14:09, David Brown wrote:

    [...]  (I don't know why N3377 proposed "do { } while NAME ( )"
    rather than "do NAME { } while ( )". )

    Oh! - I can only think that it would then be (sort of) "consistent"
    with the place of the label attacked in a 'while' loop; i.e. behind
    the 'while' keyword. - It's inconsistent in another interpretation,
    though; and I'd certainly have favored the latter form, to have the
    label consistently attached at the loop-entry keyword.

    I'd prefer label consistently attached to the loop-exit keyword. Unfortunately, for() and while() loops have no such keyword.

    I see your point, but I disagree.

    Let's say we have a language where the end of a loop is marked by a
    keyword.

    WHILE condition
    statement;
    statement;
    ENDWHILE;

    Now we want to add the ability to break out of a specified loop,
    possibly from within a nested construct. With your preference:

    WHILE condition
    statement;
    if (error) break OUTER; ENDIF;
    statement;
    OUTER: ENDWHILE;

    Putting the label at the bottom of the loop does show more clearly
    the point in the code to which the "break" transfers control. In my
    opinion, that's not a good thing.

    With the label name at the top:

    OUTER:
    WHILE condition
    statement;
    if (error) break OUTER; ENDIF;
    statement;
    ENDWHILE;

    "OUTER" is *the name of the loop*, and the entire loop is the
    construct to which "break OUTER" applies.

    If the syntax emphasizes the point to which the break jumps, I
    don't see much advantage over goto.
    --
    Keith Thompson (The_Other_Keith) [email protected]
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@[email protected] to comp.lang.c on Sun Oct 18 18:34:34 2026
    From Newsgroup: comp.lang.c

    Michael S <[email protected]> writes:
    [...]
    All I wanted to say is that I prefer label to be located at where the
    break goes. Or near this point. Within frame of current C syntax, I
    don't see how to achieve it, except for do-while. But it does not
    change the fact that I find it desirable.

    There is a way to achieve it: "goto".

    [...]
    --
    Keith Thompson (The_Other_Keith) [email protected]
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@[email protected] to comp.lang.c on Mon Oct 19 01:56:22 2026
    From Newsgroup: comp.lang.c

    On Sun, 18 Oct 2026 23:51:25 -0000 (UTC), Waldek Hebisch wrote:

    Writing statement with parentheses may look silly, but such code may
    be easily produced due to use of macros.

    Why do you need to distinguish between “statements” and “expressions”, anyway?

    By the way, the precursor of C, BCPL, allowed statement sequences
    inside expressions. For some reason this got dropped from C.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@[email protected] to comp.lang.c on Sun Oct 18 19:37:36 2026
    From Newsgroup: comp.lang.c

    Lawrence D’Oliveiro <[email protected]d> writes:
    On Sun, 18 Oct 2026 23:51:25 -0000 (UTC), Waldek Hebisch wrote:
    Writing statement with parentheses may look silly, but such code may
    be easily produced due to use of macros.

    Why do you need to distinguish between “statements” and “expressions”,
    anyway?

    Because C strongly distinguishes between statements and expressions.

    If you don't want to make that distinction, you'll need to use a
    different language.

    (The context was that a suggested change to C would be syntactically ambiguous.)

    By the way, the precursor of C, BCPL, allowed statement sequences
    inside expressions. For some reason this got dropped from C.

    Yes.

    There is a proposal to add statement expressions to C, based on
    the existing gcc extension. This is not reflected in the latest
    C2y draft.

    Note that statements and expressions are still distinct. An
    expression statement can be formed from an expression by adding
    a semicolon. A statement expression (given the extension) can be
    formed from a compound statement by adding parentheses.

    https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3643.htm
    --
    Keith Thompson (The_Other_Keith) [email protected]
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From antispam@[email protected] (Waldek Hebisch) to comp.lang.c on Mon Oct 19 08:46:58 2026
    From Newsgroup: comp.lang.c

    bart <[email protected]> wrote:
    On 18/10/2026 15:27, David Brown wrote:
    On 18/10/2026 15:33, bart wrote:
    On 18/10/2026 12:22, David Brown wrote:

    To me, that is just as much gibberish as the original C.

    That doesn't matter - the problem is not even knowing what it represents. >>
    That is, shall we say, a strange attitude.  Gibberish (since that seems
    to be the preferred term here) is gibberish, no matter the language or
    representation, and is equally meaningless and useless.

    'Gibberish' here refers to the representation, whether the type being described is made-up nonsense or real.

    You may want to know what some complex type is for many reasons, you
    don't necessarily need to understand what it means or why it was used.

    (For example I might come across a type in a C API that I want to
    convert to another language.)

    You say that you had commercial product, but you are apparently not
    aware of basic marketing principles. You do not win in the market
    by making easy switch from your product to competitor product. You
    may want to make it easy to switch _to_ your product. But you want
    to make switching to competing products as hard as possible. Of
    course there are constraints on this, in the process you do not want
    to deteriorate quality of your product too much and you have finite
    development resources.

    Judging on this criteria you should admit that C is pretty good:
    people wrote translators from various languages to C, but there
    seem to be no success story going in opposite direction. C++
    managed to take over nontrivial part of market previously occupied
    by C, but they did this by embedding largish subset of C and by
    massvie pileup of extra features.
    --
    Waldek Hebisch
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@[email protected] to comp.lang.c on Mon Oct 19 11:16:12 2026
    From Newsgroup: comp.lang.c

    On 18/10/2026 21:38, Michael S wrote:
    On Sun, 18 Oct 2026 20:47:13 +0200
    David Brown <[email protected]> wrote:

    On 18/10/2026 17:16, Michael S wrote:
    All I wanted to say is that I prefer label to be located at where
    the break goes.

    In C2y, you /do/ put the label along with the break - you write
    "break outer;". But you also have to put the label "outer : " at the
    start of the control structure.

    If you want to have some kind of "break to outer structure" /without/
    having a name or label on the structure, then you need some other way
    to refer to it. I thought you had said before your preference was
    for something like "break_switch" (ignoring any bike-shedding on the
    syntax), which would work in the particular case of a switch with
    nested loop(s). And as I wrote, this was considered and dismissed.
    (Equally, the other plausible syntax that does not require an
    explicit label - "break <depth>", was considered and dismissed.)

    Or near this point. Within frame of current C syntax, I
    don't see how to achieve it, except for do-while. But it does not
    change the fact that I find it desirable.


    Am I right in thinking you would then have :

    do {
    switch (...) {
    break outer;
    while outer (...);

    You are happy with labelling the loop or switch, but want the label
    at the end, not the start?


    Almost. I want it at the end and I want it with syntax that can't be
    confused with regular goto targets.


    I can appreciate wanting a syntax that is distinct from regular labels
    for "goto".

    (I can also appreciate that others prefer a similarity - they want to be
    able to use the same label for "goto", it means less new learning, and
    fewer conflicts with things like syntax highlighters. Since I
    personally don't expect to use the feature much, and have almost no use
    for "goto" or labels today, I am ambivalent here, and prefer to leave
    the decision to those with more direct experience. There has been
    plenty of discussion on the pros and cons here.)

    However, I am curious as to why you see putting the name or label at the
    end of the loop or switch as important. A "break <name>" will go to the
    end, but a "continue <name>" will go back to the start. Do you see
    "break" as more common or more important than "continue" ? Goto labels
    are an exception, but the normal rule in C is that names are introduced
    before their use.


    Why not then just use "goto" and put a label at the end of the loop
    or switch? (This is allowed in C23.)


    Like just about everybody else, I prefer weaker control transfers. They
    are not easier to write, but easier to follow by reader.
    goto is too powerful - can go everywhere within function. That part is improved by C2y proposal.

    (I am not sure that "weak" or "strong" is the right adjective here - I
    see "for" and "while" as /stronger/ than "goto" because they provide
    more structure and guarantees about the control flow. But I know what
    you mean, and agree with you.)

    But the labels that goto targets are also too powerful - they can be
    reached from everywhere in the function. That part is not just not
    improved by proposal, but made worse, because now we not just have a
    too powerful label (that we have to name, which is problem by itself,
    but lesser evil than break N alternative), but this label creates
    another, completely unnecessary, target for goto, that the reader of
    code should have in mind.

    Labelled breaks can eliminate a significant use of "goto". (And if
    "defer" makes it into C2y and gains popularity - admittedly a big "if" -
    that could eliminate the other major use of "goto".) If there is no
    "goto" in the function, there is no concern about where it might go.

    There is always going to be scope for misunderstanding, no matter what
    syntax is used. It is good to pick a syntax that reduces the risk, but
    it cannot be eliminated - ultimately, individual programmers are
    responsible for writing clear code.

    I think your concerns are valid, but I think (or hope) that they are
    more pessimistic than realistic.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From antispam@[email protected] (Waldek Hebisch) to comp.lang.c on Mon Oct 19 09:18:42 2026
    From Newsgroup: comp.lang.c

    Dan Cross <[email protected]> wrote:
    In article <11b0mfv$j5ll$[email protected]>, bart <[email protected]> wrote:

    C is a terrible choice for a cross-language API, as too many C-isms
    creep in (like C macros, or vaguely defined types, including the famous >>'plain char' that exists in no other language, which is neither signed
    nor unsigned, and above all C preprocessor features).

    That's why ABIs matter.

    Look at the Vax-11 Procedure Calling and Condition Handling
    Standard from VMS 2.0; they simply wrote down what this stuff
    meant, and you could call between essentially any language on
    that system, whether it was C, Fortran, Bliss, COBOL, or
    whatever.

    That is getting off-topic, but I looked at VMS documentation.
    Simple cases are described with a lot of details. But I was
    unable to find general case. Say, given array of structs
    containing notrivial types like arrays inside. It seems that
    for such types it is essentially "whatever language processor
    decides to do" and the other end must know the convention.
    Which seem to be exactly what happens on other platforms.
    --
    Waldek Hebisch
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@[email protected] to comp.lang.c on Mon Oct 19 12:26:25 2026
    From Newsgroup: comp.lang.c

    On 19/10/2026 00:20, bart wrote:
    On 18/10/2026 20:09, David Brown wrote:
    On 18/10/2026 18:09, bart wrote:

    Isn't that the problem? C makes it tricky. Here are two very
    straightforward declarations from my projects:

       ref []ichar stringtable               # ichar is ref char
       [N]ref proc(T) handlertable

    Are you suggesting that in your language, "stringtable" could also be
    declared as :

         ref ichar [stringtable]
    or
         ][ stringtable ichar ref
    ?

    (Warning: longer post than I'd intended.)

    I think you're clutching at straws.

    I am simply mocking your suggestion that "requiring the syntactical
    elements to be in the right place" is a "problem" unique to C.

    I'm snipping the irrelevant stuff about your language - I don't know why
    you bother posting it. I also don't know why you bothered inventing new meaningless combinations of pointers, arrays and functions.


    So, what do you think the purpose of CDECL is? Since to you, NOTHING
    about C type syntax ever appears to be a problem.

    I've never had any use of CDECL - it has no purpose to me. I doubt if
    many people use it except for extreme artificial examples.



    Just admit that the whole concept was a failure. The creators have
    already done so.

    The early C designers have said that the declaration syntax for C ended
    up more complex than it could have been, and with hindsight they would
    have picked a different syntax. Fair enough. But they did not "admit
    that the whole concept was a failure". Anyone who has used C
    significantly (like anyone who has used any programming language significantly) has things about the language and syntax that they
    dislike and think could have been better. But no language has had
    comparable success to that of C. It is utterly laughable to say that
    "the whole concept of C's declaration syntax was a failure".


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@[email protected] to comp.lang.c on Mon Oct 19 03:50:56 2026
    From Newsgroup: comp.lang.c

    David Brown <[email protected]> writes:
    [...]
    I can appreciate wanting a syntax that is distinct from regular labels
    for "goto".

    So can I. The first language I used that had this kind of thing
    was Ada. In the language's initial design, it was decided that
    though goto statements were needed, the labels should stand out:

    <<LABEL>>
    -- ...
    goto LABEL;

    Names used for loops have a lighter-weight syntax:

    LOOP_NAME:
    while condition loop
    -- ...
    end loop;

    I can't think of a better syntax for loop names than "NAME:" (used
    by several other languages), but in C that syntax is already
    taken for goto labels. The possibility of any ambiguity between
    "goto NAME;" and "break NAME;" doesn't bother me enough to want
    to invent something new. And I consider the fact that other
    languages use the "NAME:" syntax for loop names to be another
    point in its favor.

    The odd scoping rules for labels don't bother me either. They mean
    you can't have two loops or switch statements with the same name in
    the same function. I can barely imagine that being inconvenient.

    And it's already specified in the latest C2y draft, and implemented in
    gcc and clang, which means there's already some inertia against any
    major changes. Anything could happen between now and the publication
    of the next C standard, but I don't see any need to make significant
    changes in this area.

    I use Perl's equivalent of named break quite a lot. I found
    31 occurrences of "exit NAME" in a collection of Perl scripts
    I've written. I'm a little surprised to find that none of these
    break out of nested loops; I just like to name loops for clarity.
    I even find that having to choose a name for something forces
    me to think more clearly about it.

    The C2y proposed syntax and semantics for named loops and switch
    statements is of course imperfect, but it's reasonably clean
    and useful. I see no need to make any significant changes in
    this area.

    [...]
    --
    Keith Thompson (The_Other_Keith) [email protected]
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@[email protected] to comp.lang.c on Mon Oct 19 12:59:00 2026
    From Newsgroup: comp.lang.c

    On 19/10/2026 12:50, Keith Thompson wrote:
    David Brown <[email protected]> writes:
    [...]
    I can appreciate wanting a syntax that is distinct from regular labels
    for "goto".

    So can I. The first language I used that had this kind of thing
    was Ada. In the language's initial design, it was decided that
    though goto statements were needed, the labels should stand out:

    <<LABEL>>
    -- ...
    goto LABEL;

    Names used for loops have a lighter-weight syntax:

    LOOP_NAME:
    while condition loop
    -- ...
    end loop;

    I can't think of a better syntax for loop names than "NAME:" (used
    by several other languages), but in C that syntax is already
    taken for goto labels. The possibility of any ambiguity between
    "goto NAME;" and "break NAME;" doesn't bother me enough to want
    to invent something new. And I consider the fact that other
    languages use the "NAME:" syntax for loop names to be another
    point in its favor.

    The odd scoping rules for labels don't bother me either. They mean
    you can't have two loops or switch statements with the same name in
    the same function. I can barely imagine that being inconvenient.

    I can imagine that being a bit inconvenient in some cases, but I think
    the proposal in N3658 would simply and cleanly fix that.


    And it's already specified in the latest C2y draft, and implemented in
    gcc and clang, which means there's already some inertia against any
    major changes. Anything could happen between now and the publication
    of the next C standard, but I don't see any need to make significant
    changes in this area.

    I use Perl's equivalent of named break quite a lot. I found
    31 occurrences of "exit NAME" in a collection of Perl scripts
    I've written. I'm a little surprised to find that none of these
    break out of nested loops; I just like to name loops for clarity.
    I even find that having to choose a name for something forces
    me to think more clearly about it.

    The C2y proposed syntax and semantics for named loops and switch
    statements is of course imperfect, but it's reasonably clean
    and useful. I see no need to make any significant changes in
    this area.


    There are always going to be disagreements about language features and
    syntax - even more so when they are added late to a language, rather
    than part of the initial design. (Maybe if named loops and "defer" were
    part of the original C, it would never have needed "goto" and labels.)
    Changes and additions have to be of enough potential benefit, and low
    enough cost or potential confusion - they don't have to be "perfect" or
    suit the needs and preferences of everyone.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Mon Oct 19 12:47:27 2026
    From Newsgroup: comp.lang.c

    On 19/10/2026 02:19, Dan Cross wrote:
    In article <11b0mfv$j5ll$[email protected]>, bart <[email protected]> wrote:

    I see that you convenient snipped out my comment about C++,
    which is the direct counter example.

    I don't want to discuss C++. That language is abominable, other than as
    the go-to example of language design going very wrong.

    "Had" is a strong word; dare I say it...a subjective word.

    In fact, there have been all kinds of alternatives for years.
    In the earlish 1980s, there was Modula-2, PL/M, Forth, Ada, CLU,
    BLISS, and so on. You yourself admit you started from Algol68.
    By the late 1980s you had Oberon, decent versions of ML, C++
    and Objective-C, etc; by the 1990s, there were more than you
    could shake a stick at. Now? Take your pick.

    You never "had" to use your own language.

    OK. But they HAD to create C? There were quite a few languages in the
    early 70s too: like Pascal, Fortran, PL/I, Coral-66, plus of course BCPL
    and B. So why a new one?

    Anyway you don't know my circumstances. My homemade machine had
    absolutely ZERO software. I literally had to start from binary machine
    code, as there was no keyboard at first (more below).

    I also never used Algol68; I'd only seen it in a book.

    In my job later I was an engineer, not a programmer, and there was no
    budget for software such as compilers. But they would anyway have been a nightmare to install (floppy disk formats were not standard!), and would
    been hopelessly slow to use.

    The language I ended up creating was perfect for my needs and compiled
    more or less instantly.

    You do know; you just don't want to admit it. (Imagine introducing C
    declarations into a current language.)

    No, really; C's declaration syntax was inspired by FORTRAN, and
    generations of scientists and engineers have managed that
    language just fine.

    FORTRAN syntax looked nothing like C! Unless you mean the general
    pattern of 'INTEGER A, B' which was shared by half of all languages.

    (I spent a year writing FORTRAN on mainframes and minicomputers.)

    Generations of programmers have handled C's
    all right as well.

    How many gave up because it was too much? How many still struggle with
    it and have to employ those 4 or 5 workarounds which I mention
    elsewhere? How much has it affected productivity?

    Your statement is meaningless. Maybe some task (in any sphere) takes 17
    steps to achieve. People will manage. But then somebody figures out how
    to do it in 3 steps; that's better right?

    No, according to you: let's stick with 17 steps; people have always
    managed, and 10 million people can't be wrong!

    Then why do you keep bringing your language up, showing snippets
    of its syntax, and so on?

    Suppose that language didn't exist. I guess then it would be OK to bring
    up hypothetical new features and bits of syntax here? People do it all
    the time (even Keith did today, of all people).

    But if those examples come from an actual, working and proven
    implementation, which lend them more weight, then it is not allowed and
    the examples then become irrelevant?

    I guess it is not playing the game in that case?
    Why hasn't there long been an alternative systems language that didn't
    have C's crazy syntax and stupid quirks? I mean like 30-50 years ago.

    There...have been? And still are?

    In that case, why has C itself been so heavily used, in OSes, drivers,
    and endless libraries, rather than one those which you suggest I adopt?

    I needed a language that worked at a lower level, could access hardware,
    had inline assembly, had a weak type system that allowed all sorts of underhand methods /to get things done/.

    And that is exactly what I created in the early 80s, along with, as it
    turned out, very fast implementations.

    C would also have been a good fit, and presumably why it was so popular
    for actual systems programming tasks.

    So WHAT C does is good; HOW it does it is bad - in my opinion, and lots
    of others. The difference is others have be work with it, while I had
    the choice of persevering with mine.

    Still, this is C in 2026:

    #include <stdint.h>
    uint8_t a, b, c;

    This is mine in 1981 and in 2026

    byte a, b, c

    Yes, mine has lots of examples of how some alternative features could
    work; so what? I am not selling my language.

    Oh good, so you'll stop bringing it up?

    Forget the actual language: why is not possible to concentrate on some specific feature or approach, and consider that in isolation and without
    bias?

    It either has merit or it hasn't. In any case, when I posted a link to
    that document about my language, people (especially JP) said it was
    derivative with nothing new.

    So that's OK then? Just pretend some feature has been used in some more
    famous language.

    Not really, no. I don't do Windows,

    OK. I mentioned it because some people don't believe my language exists.
    I have posted links to working versions over the years, but I usually
    found that a waste of time, as now. (I still had to prepare and test the version I'd have linked to.)


    But this sort of thing is exactly what I'm talking about: your
    language is not useful beyond a userbase of one.

    That is 100% not true. It would be useful to anyone working on Windows
    or even Linux. But it was never intended as a product used by other
    people. As I said I'm not selling it, and would not want to support it.

    You solved a
    set of "problems" that you defined for yourself, whether they
    were real or not,

    The scope of my language seems to overlap with the scope of C.

    and now are now sitting here trying to use
    that as evidence about a general argument based on false
    premises ("there was no alternative! I _had_ to do my own
    thing!"

    I gave you my circumstances above. What would /you/ have done?

    That's why ABIs matter.

    You're confusing APIs and ABIs.

    ABIs are a matter for compilers. Translating APIs into a set of bindings
    for another language is someone else's job.

    So you can't use limited resources as an excuse for its questionable
    choices. Actually some choices actually made it harder to parse.

    The team that created C was familiar with, and rather liked,
    Richard Martin's BCPL. B was created as sort of a chopped down
    BCPL that could fit on the PDP-7, a machine with 4KW of 18-bit
    core memory, at an access time of ~1.5ms, where most
    instructions touch memory twice. Oh, and that machine was
    running a multitasking, multiuser operating system and was
    self-hosting. And you are seriously comparing your single-user
    home PC with 64k of RAM to that environment? I'm not sure you
    know what "hardware limitations" are.

    My first machine actually had 256 bytes of RAM, no input, no output, and unreliable cassette tape storage made with shift registers and counters.

    I had ZERO existing software. No money. I didn't work in academia, nor
    in a company, had no people to help. There weren't lots of other,
    existing machines and terminals lying around to prepare programs on.

    Yes the hardware was more compact and cheaper compared with 1970
    (although SRAM still cost £24,000,000 per GB -- in 1981 money!) but I
    was lacking everything else.

    In any case, we're talking about C. Was a PDP 11/20 less powerful than a 2.5MHz Z80 with the 32KB I ended up with? I've no idea. But the crude
    language I created FROM NOTHING still looked like this:

    int a, b, c
    println a + b

    As mentioned, C came from B, once they got a PDP-11; it was an
    incremental evolution of a language they already had. The type
    syntax you find so distasteful was inspired by FORTRAN.

    Please give an example of FORTRAN that looks like C.

    It's so weird to me that you make such absolute pronouncements
    about C and the choices that into its design, but are so
    ajbectly ignorant of the actual history. Bluntly, you just are
    not very well informed about it to make cogent comments.

    How does knowing the history in such detail help? If a feature stinks,
    it stinks.

    See my post yesterday about the impact choosing a prefix dereference op instead of postfix made on the language. It was probably even more far-reaching than stated.

    And yet Pascal was right there!

    That choice had nothing to with limited hardware; it was just the wrong one. --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@[email protected] (Dan Cross) to comp.lang.c on Mon Oct 19 12:00:46 2026
    From Newsgroup: comp.lang.c

    In article <11b4n9g$4fik$[email protected]>,
    Waldek Hebisch <[email protected]> wrote:
    Dan Cross <[email protected]> wrote:
    In article <11b0mfv$j5ll$[email protected]>, bart <[email protected]> wrote:

    C is a terrible choice for a cross-language API, as too many C-isms >>>creep in (like C macros, or vaguely defined types, including the famous >>>'plain char' that exists in no other language, which is neither signed >>>nor unsigned, and above all C preprocessor features).

    That's why ABIs matter.

    Look at the Vax-11 Procedure Calling and Condition Handling
    Standard from VMS 2.0; they simply wrote down what this stuff
    meant, and you could call between essentially any language on
    that system, whether it was C, Fortran, Bliss, COBOL, or
    whatever.

    That is getting off-topic, but I looked at VMS documentation.
    Simple cases are described with a lot of details. But I was
    unable to find general case. Say, given array of structs
    containing notrivial types like arrays inside. It seems that
    for such types it is essentially "whatever language processor
    decides to do" and the other end must know the convention.
    Which seem to be exactly what happens on other platforms.

    I imagine in that case one would use an array descriptor to
    describe the array, and then a more specific descriptor (or set
    of) to describe the structure of each element of the array.

    In any event, the thing they did that's relevant here is
    describing the properties of the basic types (what the VAX-11
    run-time library reference manual calls, "atomic types", which
    should not be confused with what we now call atomic types, that
    have specific properties on multi-CPU systems; the VMS 2.0 docs
    just meant the primitive data types understood by the VAX
    hardware; bytes words, long/quad/octowords, and so on).

    The point I was trying to make, and how it's relevant to C, is
    that this is an early-ish example of what we now would think of
    as an ABI, and it made (say) inter-language procedures calls
    tractable. I don't know quite how to articulate it in a way
    that won't kick over the language-lawyer hornet's nest, but
    informally, the C standard doesn't mandate any particular ABI,
    and indeed, tries to steer clear of such things to the extent
    that it can. Bart complains about the need to deal with the "C
    API", but really, he's referring to ABI issues ("is `char`
    signed or not?" The ISO C doesn't say, but within each ABI, we
    know.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@[email protected] to comp.lang.c on Mon Oct 19 14:08:54 2026
    From Newsgroup: comp.lang.c

    On 19/10/2026 13:47, bart wrote:
    On 19/10/2026 02:19, Dan Cross wrote:
    In article <11b0mfv$j5ll$[email protected]>, bart  <[email protected]> wrote:

    I see that you convenient snipped out my comment about C++,
    which is the direct counter example.

    I don't want to discuss C++. That language is abominable, other than as
    the go-to example of language design going very wrong.

    And yet it is another /massively/ successful language. Perhaps you are correct that C and C++ are terrible designs - but that would mean "good"
    and "bad" language design has nothing much to do with how successful a language is, or how many people manage to use the language to write
    good, working, useful software. Mind you, we have no examples of
    languages that you consider "good" language design, other than your own languages.


    "Had" is a strong word; dare I say it...a subjective word.

    In fact, there have been all kinds of alternatives for years.
    In the earlish 1980s, there was Modula-2, PL/M, Forth, Ada, CLU,
    BLISS, and so on.  You yourself admit you started from Algol68.
    By the late 1980s you had Oberon, decent versions of ML, C++
    and Objective-C, etc; by the 1990s, there were more than you
    could shake a stick at.  Now?  Take your pick.

    You never "had" to use your own language.

    OK. But they HAD to create C? There were quite a few languages in the
    early 70s too: like Pascal, Fortran, PL/I, Coral-66, plus of course BCPL
    and B. So why a new one?

    Check off "whataboutism" on the logical fallacy bingo card !


     Generations of programmers have handled C's
    all right as well.

    How many gave up because it was too much? How many still struggle with
    it and have to employ those 4 or 5 workarounds which I mention
    elsewhere? How much has it affected productivity?

    I have never heard of anyone giving up C because of the declaration
    syntax. Have you?

    Once you have removed pathological examples, I have not seen anyone but
    C newbies have trouble with real-world C declarations - and having
    trouble when you are new to a language is perfectly normal for all
    languages.

    And by "workarounds", do you mean language features for working with types?

    I have heard people complain about C's declaration syntax, and heard
    people say it is weird, or ugly, or counter-intuitive - but not that it actually causes real productivity problems, real bugs, or chases people
    away from the language. Any point you may have had has been long lost
    in your wild exaggerations.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@[email protected] to comp.lang.c on Mon Oct 19 15:16:40 2026
    From Newsgroup: comp.lang.c

    On 2026-10-18 21:09, David Brown wrote:
    On 18/10/2026 18:09, bart wrote:
    [...]
    [ declaration syntax ]

    (I just want to comment on a [not unimportant] detail...)


    You need to give things in the right order, or use parentheses, to get
    the right "type expression".  It's just like any other kind of expression.

    The intention of the declaration syntax in C is that the declaration
    order follows usage.  [...]

    I think the first part is downplaying that languages typically indeed
    make a distinction between parenthesized expressions and declarations.
    Quite some other languages [not from the C-heritage] that I used all
    did not need to introduce "expression"-grouping for _declarations_ in
    the first place given their more consistent ways to declare entities.

    The second part is, as I had understood C's history, the idea behind
    how it got defined; needless to say that I think that was a bad idea.
    But that's what we've got! If they had dropped that requirement/idea
    the declaration syntax could have become "better" (more consistent,
    less cryptic, less convoluted, clearer). Now, after half a century,
    we just have to live with that, and folks who have "problems" with it
    should better not touch this language (or maybe not doing programming
    at all). The somewhat tragic aspect is that the "declaration follows
    use" idea was (IIRC) intended to _simplify_ the understanding of its
    concepts and use of the language; the consequences were seemingly not
    valued correctly.

    Janis

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@[email protected] to comp.lang.c on Mon Oct 19 15:44:40 2026
    From Newsgroup: comp.lang.c

    On 2026-10-18 18:32, Michael S wrote:
    On Sun, 18 Oct 2026 18:11:18 +0200
    Janis Papanagnou <[email protected]> wrote:
    On 2026-10-18 17:26, Michael S wrote:
    On Sun, 18 Oct 2026 16:58:38 +0200
    David Brown <[email protected]> wrote:
    On 18/10/2026 16:24, Michael S wrote:
    [...]
    It would be interesting to find out why designers of C, or of one
    of its ancestors decided that * as prefix is preferable to * as
    postfix.

    Because it is more "natural" when read, easier to grasp?

    IMHO, no.

    Okay, if you think so.


    Simpler for compilers?

    100% no.

    I've read that would be a, albeit small, existing factor (when
    resolving ambiguities or some such; but I don't recall details).
    Anyway, I just want to mention some existing purported arguments,
    so I take your word as granted.


    More consistent if all other, especially standard
    operators known from daily use are used in prefix-form (-5, +42,
    !false, ~bitset) in expressions?

    Unary * is more similar in function to postfix operators like [] and ()
    than to those you mentioned.

    I don't know how you come to that opinion. Personally I've learned
    the concepts in abstract, non-language-specific forms as 'deref';
    "deref p" not "p deref"; to me the former looks more natural, but
    we can agree that this may be just our personal preferences).

    (A less low-level language will ideally anyway abstract from any
    explicit dereferentiation, but since we're speaking about "C" I'm
    not expanding further on that.)



    I don't recall to have used any language with infix-expressions
    that would have their monadic operators defined in postfix form.

    I am a Bear of Very Little Brain, and long words Bother Me.

    (If that quote is important for your argument, please explain.)


    By chance, did you never use Pascal?

    Oh, yes, how could I forget that! (I stand corrected.) - I suppose
    it's because I considered that more an "accessor" than an operator
    (like the array or struct selectors); that's also why it's often
    not listed in Pascal's operator precedence tables. - So thanks for
    the reminder.

    Janis

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@[email protected] to comp.lang.c on Mon Oct 19 15:46:00 2026
    From Newsgroup: comp.lang.c

    On 19/10/2026 15:16, Janis Papanagnou wrote:
    On 2026-10-18 21:09, David Brown wrote:
    On 18/10/2026 18:09, bart wrote:
    [...]
    [ declaration syntax ]

    (I just want to comment on a [not unimportant] detail...)


    You need to give things in the right order, or use parentheses, to get
    the right "type expression".  It's just like any other kind of
    expression.

    The intention of the declaration syntax in C is that the declaration
    order follows usage.  [...]

    I think the first part is downplaying that languages typically indeed
    make a distinction between parenthesized expressions and declarations.
    Quite some other languages [not from the C-heritage] that I used all
    did not need to introduce "expression"-grouping for _declarations_ in
    the first place given their more consistent ways to declare entities.

    The second part is, as I had understood C's history, the idea behind
    how it got defined; needless to say that I think that was a bad idea.
    But that's what we've got! If they had dropped that requirement/idea
    the declaration syntax could have become "better" (more consistent,
    less cryptic, less convoluted, clearer). Now, after half a century,
    we just have to live with that, and folks who have "problems" with it
    should better not touch this language (or maybe not doing programming
    at all). The somewhat tragic aspect is that the "declaration follows
    use" idea was (IIRC) intended to _simplify_ the understanding of its
    concepts and use of the language; the consequences were seemingly not
    valued correctly.

    There are a number of things that I don't particularly like about C's declaration syntax, or where I think it would have been better if it
    were different. But the "inside-to-outside" ordering is not one of
    them. That is not because I think it is better or clearer than
    left-to-right ordering, but because when I compare to, say, Pascal, it's
    not a big issue for me. Far bigger are :

    1. People put too much into a single type declaration, rather than
    building types out of logical parts with a purpose and a name. They
    don't do it as much as Bart likes to pretend, but some people do it too
    much for my liking. The language doesn't force you to do that - it's programmer style. IMHO there is never a reason for a "pointer to an
    array of function pointers taking int and returning void" - no matter
    what syntax is used. Give a name to the function pointer type that
    reflects the usage (/not/ a name that reflects the definition), and
    build up from there.

    2. Being able to declare variables and functions with different types in
    the same declaration. Very occasionally, I find it convenient to
    declare more than one variable at once - "int a, b, c;". It is rare in
    my code - generally it is one variable with an initialiser (and perhaps
    a comment) at a time. But it is - IMHO - a bad thing that you can write
    "int a, xs[20], *p, (*f)(void);" in one declaration.

    Both of these are overcome by simply not writing code that way.
    Obviously that is easy to achieve in my own code, but other people may
    use a different style.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Mon Oct 19 15:00:03 2026
    From Newsgroup: comp.lang.c

    On 19/10/2026 09:46, Waldek Hebisch wrote:
    bart <[email protected]> wrote:
    On 18/10/2026 15:27, David Brown wrote:
    On 18/10/2026 15:33, bart wrote:
    On 18/10/2026 12:22, David Brown wrote:

    To me, that is just as much gibberish as the original C.

    That doesn't matter - the problem is not even knowing what it represents. >>>
    That is, shall we say, a strange attitude.  Gibberish (since that seems >>> to be the preferred term here) is gibberish, no matter the language or
    representation, and is equally meaningless and useless.

    'Gibberish' here refers to the representation, whether the type being
    described is made-up nonsense or real.

    You may want to know what some complex type is for many reasons, you
    don't necessarily need to understand what it means or why it was used.

    (For example I might come across a type in a C API that I want to
    convert to another language.)

    You say that you had commercial product, but you are apparently not
    aware of basic marketing principles. You do not win in the market
    by making easy switch from your product to competitor product. You
    may want to make it easy to switch _to_ your product. But you want
    to make switching to competing products as hard as possible. Of
    course there are constraints on this, in the process you do not want
    to deteriorate quality of your product too much and you have finite development resources.

    Judging on this criteria you should admit that C is pretty good:
    people wrote translators from various languages to C, but there
    seem to be no success story going in opposite direction.

    There are lots of reasons why not.

    C is popular as a compiler target because it is lower level than the
    source language. It has a weak type system which is easy to circumvent.

    It has 'goto'! (Many languages don't)

    There are well established, ubiquitous optimising compilers for it.

    Now, what would be the reasons for going the other way? There aren't any!

    (Well, some languages may have a feature to translate C programs into
    their syntax so that development can proceed in the new language. But
    the start point here is not C code being used for development, with some
    other HLL as an intermediate form.)

    So for that purpose, C is probably the most practical of current HLLs.

    Even if it is still not ideal and there are features which are awkward
    to express as C. C's UBs also get in the way.

    I've tried several times myself both with high-level and low-level
    generated C.

    (However, as a target language, I recently tried my own for that
    purpose, and it worked perfectly! Some features such as out-of-order definitions made it easier than C.

    Of course, my product does not have optimising compilers and very
    limited targets, due to not having an army of 1000s taking care of that
    as happens with C.

    But it shows that the creating such a suitable language design is not hard.)


    C++
    managed to take over nontrivial part of market previously occupied
    by C, but they did this by embedding largish subset of C and by
    massvie pileup of extra features.

    So why IS C still around given that C++ compiler can build C programs,
    more or less?

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@[email protected] to comp.lang.c on Mon Oct 19 16:03:29 2026
    From Newsgroup: comp.lang.c

    On 2026-10-19 15:46, David Brown wrote:
    On 19/10/2026 15:16, Janis Papanagnou wrote:
    [...]

    There are a number of things that I don't particularly like about C's declaration syntax, or where I think it would have been better if it
    were different.  But the "inside-to-outside" ordering is not one of
    them.  That is not because I think it is better or clearer than left-to- right ordering, but because when I compare to, say, Pascal, it's not a
    big issue for me.  Far bigger are :

    1. People put too much into a single type declaration, rather than
    building types out of logical parts with a purpose and a name.

    Yes, that can be regularly observed, and not only in case of the
    declaration but generally; with known building blocks you can
    construct arbitrary complex expressions incrementally, so it might
    not appear as a problem at the time one writes it. But then parsing
    complex expressions - say, if that code is from another person or
    source - it gets difficult. (Topic reminds me Regexp expressions.)
    But also program composition in general is sometimes following an
    incremental growing process. Structuring is the key.

    They
    don't do it as much as Bart likes to pretend, but some people do it too
    much for my liking.  The language doesn't force you to do that - it's programmer style.  IMHO there is never a reason for a "pointer to an
    array of function pointers taking int and returning void" - no matter
    what syntax is used.  Give a name to the function pointer type that reflects the usage (/not/ a name that reflects the definition), and
    build up from there.

    I fully agree.

    Where I obviously have a different valuation is that I saw in other
    languages' contexts that there's less issues with this topic.


    2. Being able to declare variables and functions with different types in
    the same declaration.  Very occasionally, I find it convenient to
    declare more than one variable at once - "int a, b, c;".  It is rare in
    my code - generally it is one variable with an initialiser (and perhaps
    a comment) at a time.

    Absolutely the same for me.

    But it is - IMHO - a bad thing that you can write
    "int a, xs[20], *p, (*f)(void);" in one declaration.

    I agree. - But as opposed to other posters that's no serious problem;
    "if it hurts, just don't do it".


    Both of these are overcome by simply not writing code that way.

    (I should have read your post to the end before my previous statement.)

    Obviously that is easy to achieve in my own code, but other people may
    use a different style.

    And that's why companies instantiate coding standards.

    Janis

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@[email protected] to comp.lang.c on Mon Oct 19 16:15:41 2026
    From Newsgroup: comp.lang.c

    On 2026-10-19 00:18, Dan Cross wrote:
    In article <11b2pq5$3pvda$[email protected]>,
    Janis Papanagnou <[email protected]> wrote:
    On 2026-10-18 16:13, Michael S wrote:
    On Sun, 18 Oct 2026 14:34:28 +0200
    Janis Papanagnou <[email protected]> wrote:
    On 2026-10-18 14:09, David Brown wrote:

    [...]  (I don't know why N3377 proposed "do { } while NAME ( )"
    rather than "do NAME { } while ( )". )

    Oh! - I can only think that it would then be (sort of) "consistent"
    with the place of the label attacked in a 'while' loop; i.e. behind
    the 'while' keyword. - It's inconsistent in another interpretation,
    though; and I'd certainly have favored the latter form, to have the
    label consistently attached at the loop-entry keyword.

    I'd prefer label consistently attached to the loop-exit keyword.

    I can see that this might look appealing in case of 'break'. In
    case of the same mechanism working also for 'continue' I'd then
    think that it should generally better be an "attribute" of the
    loop entry keyword, i.e. placed where loops start. [...]

    I think colocating it with `do` might create a syntactic
    ambiguity. In the case of `for`, `while`, and `select`, there
    is a required token following the keyword (the `(`). However,
    for a `do`/`while` loop, `do` is followed immediately by a,
    `secondary-block` production.

    Good point!

    In particular, you do not _need_
    braces to denote a compound statement after `do`; something like
    `do i++; while (i < j);` is perfectly legal in C.

    Yes.


    In the N3377 proposal, the new `block-name` is just an
    identifier. If it were allowed immediately after the `do`, then
    given, `do NAME statement; while(condition);` you can't tell
    `NAME` from the name of the loop and a random identifier before
    a statement; something like `do LOOP i++; while (i < j);`
    appears as though it _would_ be be syntactically valid by N3377
    as presently worked, but is the programmer's intent to create a
    loop name, or should this just be a syntax error?

    By requiring the block-name between a keyword and a
    syntactically required `(`, you remove that ambiguity: if there
    is an identifier there, then it is a `block-name`; if not, then
    the block has no name.

    Thanks for your elaborations.

    Janis

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@[email protected] (Dan Cross) to comp.lang.c on Mon Oct 19 14:35:06 2026
    From Newsgroup: comp.lang.c

    In article <11b4smj$1vt4q$[email protected]>,
    Keith Thompson <[email protected]> wrote:
    The odd scoping rules for labels don't bother me either. They mean
    you can't have two loops or switch statements with the same name in
    the same function. I can barely imagine that being inconvenient.

    An issue is that one might generate such a named loop with a
    macro. I can imagine that being useful for `XIMPL` type
    constructs, but C's macros are unusually weak, and C doesn't
    have something like `(GENSYM)` in Lisp, so you've got to plumb
    the loop name through the macro invocation: mildly annoying, but
    not too bad.

    Then again, if a programmer is abusing macros like that to
    generate named loops multiple times in the same function,
    then perhaps the program needs a re-think, ximpl or no.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Tim Rentsch@[email protected] to comp.lang.c on Mon Oct 19 08:47:25 2026
    From Newsgroup: comp.lang.c

    Janis Papanagnou <[email protected]> writes:

    On 2026-10-18 12:48, David Brown wrote:

    On 17/10/2026 01:29, Janis Papanagnou wrote:

    On 2026-10-17 00:00, Keith Thompson wrote:

    Tim Rentsch <[email protected]> writes:

    Keith Thompson <[email protected]> writes:
    [...]

    There's a proposal for C2y to use goto labels as loop names, and a >>>>>> competing one to define a new syntax like "for NAME (;;)" :
    [...]

    I'm not particularly a fan of multi-level break/continue. But if
    we're going to have one of these, the second ("for NAME (;;)") is
    unquestionably better.

    Unquestionably? Why?

    Why would one question an opinion? ;-)

    Time didn't word it as a personal opinion - he made it clear that he
    doesn't think anyone else could have a different opinion.

    You've noticed my smiley? (There was no need for an explanation.)

    Anyone who thinks my statement "the second ("for NAME (;;)") is
    unquestionably better" was meant as a statement of fact rather
    than a statement of opinion is an idiot.

    I think most people can see that I am careful in my writing, and
    also that I make an effort to differentiate statements of opinion,
    statements of belief, and statements of fact. My remark above is
    no exception to that practice.

    For the benefit of any other people who may have not seen the
    distinction here, please remember this: any statement that uses
    the word "better", when made without any reference to some sort of
    objective metric, is inherently a subjective statement. Any
    subjective statement (that does not fall into the category of
    being a statement of belief) is a statement of opinion. It's easy
    to see this simply by a process of elimination, because subjective
    statements are not facts, and vice versa.

    The C standards committee collectively reached an agreement counter
    to Tim's thoughts, so clearly his preferred variant is /not/
    unquestionably better.

    "C" is "C", and Tim is Tim. (And we know both sufficiently.) :-)

    My confidence in the collective wisdom of the ISO C committee has
    declined in recent years, and sadly for more than just the last
    few years. So learning that they have settled (even if that might
    change in the future) on the "label: for(...)" approach is
    disappointing, but not surprising.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Richard Harnden@[email protected] to comp.lang.c on Mon Oct 19 16:55:55 2026
    From Newsgroup: comp.lang.c

    On 19/10/2026 15:00, bart wrote:

    So why IS C still around given that C++ compiler can build C programs,
    more or less?

    Because it's typically less.

    I see C and C++ as very different.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@[email protected] to comp.lang.c on Mon Oct 19 18:28:43 2026
    From Newsgroup: comp.lang.c

    [ with big snips of lots of irrelevant stuff ]

    On 2026-10-19 17:47, Tim Rentsch wrote:
    On 2026-10-18 12:48, David Brown wrote:

    The C standards committee collectively reached an agreement counter
    to Tim's thoughts, so clearly his preferred variant is /not/
    unquestionably better.

    My confidence in the collective wisdom of the ISO C committee has
    declined in recent years, and sadly for more than just the last
    few years. So learning that they have settled (even if that might
    change in the future) on the "label: for(...)" approach is
    disappointing, but not surprising.

    I understand the disappointment when something evolves differently,
    where own opinions or own "educated or acquired wisdom" diverges.
    (Such expressed disappointment is observable with some other poster
    here as well.)

    Opinions are fine, arguments are better.

    The arguments (meanwhile) exchanged here let me come to another
    conclusion than you, though, concerning the competence or rather
    the thoughtfulness of the involved committee members.

    And, to come back to the primary topic; the "problems" adding such
    features to "C" (with all perceived sub-optimality of every option)
    is primarily based on how it had been designed back then. (It's not
    so much a problem of the specific "collective [committee] wisdom".
    IMHO and YMMV.)

    I don't think it makes sense to continue discussions on that level.

    Janis

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@[email protected] to comp.lang.c on Mon Oct 19 18:31:34 2026
    From Newsgroup: comp.lang.c

    On 19/10/2026 16:35, Dan Cross wrote:
    In article <11b4smj$1vt4q$[email protected]>,
    Keith Thompson <[email protected]> wrote:
    The odd scoping rules for labels don't bother me either. They mean
    you can't have two loops or switch statements with the same name in
    the same function. I can barely imagine that being inconvenient.

    An issue is that one might generate such a named loop with a
    macro. I can imagine that being useful for `XIMPL` type
    constructs, but C's macros are unusually weak, and C doesn't
    have something like `(GENSYM)` in Lisp, so you've got to plumb
    the loop name through the macro invocation: mildly annoying, but
    not too bad.

    Hopefully the N3658 fix for that will be in C2y.

    <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3658.htm>

    That will also let people - for better or worse - write things like:

    #define For Loop_label: for
    #define While Loop_label: while
    #define Switch Switch_label
    #define Break_Loop break Loop_label
    #define Break_Switch break Switch_label


    Then again, if a programmer is abusing macros like that to
    generate named loops multiple times in the same function,
    then perhaps the program needs a re-think, ximpl or no.

    - Dan C.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@[email protected] (Dan Cross) to comp.lang.c on Mon Oct 19 17:22:41 2026
    From Newsgroup: comp.lang.c

    In article <11b500f$216c4$[email protected]>, bart <[email protected]> wrote:
    On 19/10/2026 02:19, Dan Cross wrote:
    I see that you convenient snipped out my comment about C++,
    which is the direct counter example.

    I don't want to discuss C++. That language is abominable, other than as
    the go-to example of language design going very wrong.

    Oh. You don't _want_ to; I see. So you want to make statements
    about the relative "productivity" of languages but ignore the
    most prominent counter example to your argument because you
    don't _want_ to discuss C++.

    "Had" is a strong word; dare I say it...a subjective word.

    In fact, there have been all kinds of alternatives for years.
    In the earlish 1980s, there was Modula-2, PL/M, Forth, Ada, CLU,
    BLISS, and so on. You yourself admit you started from Algol68.
    By the late 1980s you had Oberon, decent versions of ML, C++
    and Objective-C, etc; by the 1990s, there were more than you
    could shake a stick at. Now? Take your pick.

    You never "had" to use your own language.

    OK. But they HAD to create C?

    Doesn't matter. They did. You weren't there; you don't know
    why they made the decisions they made, whether they gave this or
    that serious consideration and dismissed it, or were unaware of
    one thing or another, what constraints they were operating
    under, etc.

    It is _so easy_ to sit here and throw stones at people toiling
    away in the 1960's because they made decisions you don't like.
    But, bluntly, you haven't put in the work to have an opinion:
    you are ignorant of the history, and actively resist even simple
    things like reading the standard to back up your assertions;
    when you're shown to be incorrect, you double down or (yes) move
    the goalposts by making some other statement.

    You came up with your toy language and compiler in the 80s; more
    than a decade after C. It's cute that you felt you _had_ to do
    that, but you were in a completely different context than the
    1127 folks at Bell Labs who created C.

    There were quite a few languages in the
    early 70s too: like Pascal, Fortran, PL/I, Coral-66, plus of course BCPL
    and B. So why a new one?

    B _was_ a new language. Pascal as a useful language beyond
    pedagogy postdates C. Pretty much the rest of this is discussed
    in DMR's C history paper, which I'm willing to bet you haven't
    bothered to read.

    Anyway you don't know my circumstances. My homemade machine had
    absolutely ZERO software. I literally had to start from binary machine
    code, as there was no keyboard at first (more below).

    Next you'll tell us you went to the beach and picked up sand so
    you could smelt it and create your own silicon wafers, right?

    You described its capabilities. It was vastly more capable than
    a PDP-7, and it had only one user: you.

    I also never used Algol68; I'd only seen it in a book.

    You said yourself you modeled your language on Algol68; whether
    you had used it or not is irrelevant.

    In my job later I was an engineer, not a programmer, and there was no
    budget for software such as compilers. But they would anyway have been a >nightmare to install (floppy disk formats were not standard!), and would >been hopelessly slow to use.

    The language I ended up creating was perfect for my needs and compiled
    more or less instantly.

    You said you could not use a compiler and then literally
    described using a compiler.

    You do know; you just don't want to admit it. (Imagine introducing C
    declarations into a current language.)

    No, really; C's declaration syntax was inspired by FORTRAN, and
    generations of scientists and engineers have managed that
    language just fine.

    FORTRAN syntax looked nothing like C! Unless you mean the general
    pattern of 'INTEGER A, B' which was shared by half of all languages.

    That was literally the thing you said you address with
    left-to-right syntax, and that anyone who proposed such would be
    laughed at. Now it's fine, just not in C. Because C is bad.
    Or something.

    (I spent a year writing FORTRAN on mainframes and minicomputers.)

    I'm sure no one else here has done that. (*rolls eyes*)

    Generations of programmers have handled C's
    all right as well.

    How many gave up because it was too much? How many still struggle with
    it and have to employ those 4 or 5 workarounds which I mention
    elsewhere? How much has it affected productivity?

    Your statement is meaningless. Maybe some task (in any sphere) takes 17 >steps to achieve. People will manage. But then somebody figures out how
    to do it in 3 steps; that's better right?

    Maybe, maybe not. There may well be other considerations that
    factor into that decision.

    No, according to you: let's stick with 17 steps; people have always
    managed, and 10 million people can't be wrong!

    So by this metric, it's cool if a pilot just jumps into an
    airliner, turns it on, and takes off? The rest of the
    pre-flight checklist is just busywork, amirite?

    Then why do you keep bringing your language up, showing snippets
    of its syntax, and so on?

    Suppose that language didn't exist. I guess then it would be OK to bring
    up hypothetical new features and bits of syntax here? People do it all
    the time (even Keith did today, of all people).

    But if those examples come from an actual, working and proven >implementation, which lend them more weight, then it is not allowed and
    the examples then become irrelevant?

    If you want to discuss C on its merits, then discuss C.
    Unfortunately for you that would probably mean you'd have to
    actually read the relevant documentation.

    Do you _really_ think that the people who post here regularly
    are not aware that, say, other variable declaration syntaxes
    exist that are less messy than C's? No, seriously, don't give
    me some other example from your language, answer that question
    honestly: do you _really_ believe that no one here understands
    that fact, or just outright disbelieves it?

    I guess it is not playing the game in that case?
    Why hasn't there long been an alternative systems language that didn't
    have C's crazy syntax and stupid quirks? I mean like 30-50 years ago.

    There...have been? And still are?

    In that case, why has C itself been so heavily used, in OSes, drivers,
    and endless libraries, rather than one those which you suggest I adopt?

    I can think of any number of reasons: legacy, compatibility,
    tool availability, in some cases just personal preference. For
    any one of these, I'm sure that someone has already told you
    sometime in the last six months. My repeating them is unlikely
    to have any effect.

    I needed a language that worked at a lower level, could access hardware,
    had inline assembly, had a weak type system that allowed all sorts of >underhand methods /to get things done/.
    [snip same stuff over again]

    No one cares.

    [snip]
    I gave you my circumstances above. What would /you/ have done?

    Probably not spent years seething about how the rest of the
    world is wrong for making decisions I would not have.

    [snip]
    That's why ABIs matter.

    You're confusing APIs and ABIs.

    ABIs are a matter for compilers. Translating APIs into a set of bindings
    for another language is someone else's job.

    You really don't understand how multilangauge environments work,
    do you? Maybe have a look at an ABI document at some point.

    [snip sob story about walking uphill both ways in the snow]
    But the crude
    language I created FROM NOTHING still looked like this:

    int a, b, c
    println a + b

    Ok. Don't really care.

    As mentioned, C came from B, once they got a PDP-11; it was an
    incremental evolution of a language they already had. The type
    syntax you find so distasteful was inspired by FORTRAN.

    Please give an example of FORTRAN that looks like C.

    Why? What would that show?

    If you'd get over yourself for ten minutes and read the HOPL
    paper on C, you may see this:

    |Fortran influenced the syntax of declarations: B declarations
    |begin with a specifier like `auto` or `static`, followed by a
    |list of names, and C not only followed this style but
    |ornamented it by placing its type keywords at the start of
    |declarations. (https://www.nokia.com/bell-labs/about/dennis-m-ritchie/chist.html)

    It's so weird to me that you make such absolute pronouncements
    about C and the choices that into its design, but are so
    ajbectly ignorant of the actual history. Bluntly, you just are
    not very well informed about it to make cogent comments.

    How does knowing the history in such detail help? If a feature stinks,
    it stinks.

    Much of your ranting amounts to, "how could anyone have possibly
    thought this was a good idea?" Perhaps if you looked into the
    history a bit, you may become enlightened as to why anybody
    possibly thought it was a good idea.

    See my post yesterday about the impact choosing a prefix dereference op >instead of postfix made on the language. It was probably even more >far-reaching than stated.

    And yet Pascal was right there!

    Amazingly, ALGOL W used syntax much closer to C's, despite being
    the immediate predecessor of Pascal.

    That choice had nothing to with limited hardware; it was just the wrong one.

    One final quote from HOPL:
    |Although we entertained occasional thoughts about implementing
    |one of the major languages of the time like Fortran, PL/I, or
    |Algol 68, such a project seemed hopelessly large for our
    |resources: much simpler and smaller tools were called for. All
    |these languages influenced our work, but it was more fun to do
    |things on our own.

    So, they were aware of all the languages you've cited as
    influences. And yet they decided to do things differently.

    Perhaps they had their reasons. They are not (in the case of
    Ken) and were not (sadly, in the case of Dennis) idiiots or
    fools.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Mon Oct 19 20:34:37 2026
    From Newsgroup: comp.lang.c

    On 19/10/2026 18:22, Dan Cross wrote:
    In article <11b500f$216c4$[email protected]>, bart <[email protected]> wrote:
    On 19/10/2026 02:19, Dan Cross wrote:
    I see that you convenient snipped out my comment about C++,
    which is the direct counter example.

    I don't want to discuss C++. That language is abominable, other than as
    the go-to example of language design going very wrong.

    Oh. You don't _want_ to; I see. So you want to make statements
    about the relative "productivity" of languages but ignore the
    most prominent counter example to your argument because you
    don't _want_ to discuss C++.

    "Had" is a strong word; dare I say it...a subjective word.

    In fact, there have been all kinds of alternatives for years.
    In the earlish 1980s, there was Modula-2, PL/M, Forth, Ada, CLU,
    BLISS, and so on. You yourself admit you started from Algol68.
    By the late 1980s you had Oberon, decent versions of ML, C++
    and Objective-C, etc; by the 1990s, there were more than you
    could shake a stick at. Now? Take your pick.

    You never "had" to use your own language.

    OK. But they HAD to create C?

    Doesn't matter. They did. You weren't there; you don't know
    why they made the decisions they made, whether they gave this or
    that serious consideration and dismissed it, or were unaware of
    one thing or another, what constraints they were operating
    under, etc.

    It is _so easy_ to sit here and throw stones at people toiling
    away in the 1960's because they made decisions you don't like.
    But, bluntly, you haven't put in the work to have an opinion:
    you are ignorant of the history, and actively resist even simple
    things like reading the standard to back up your assertions;
    when you're shown to be incorrect, you double down or (yes) move
    the goalposts by making some other statement.

    You came up with your toy language and compiler in the 80s; more
    than a decade after C. It's cute that you felt you _had_ to do
    that, but you were in a completely different context than the
    1127 folks at Bell Labs who created C.

    There were quite a few languages in the
    early 70s too: like Pascal, Fortran, PL/I, Coral-66, plus of course BCPL
    and B. So why a new one?

    B _was_ a new language. Pascal as a useful language beyond
    pedagogy postdates C. Pretty much the rest of this is discussed
    in DMR's C history paper, which I'm willing to bet you haven't
    bothered to read.

    Anyway you don't know my circumstances. My homemade machine had
    absolutely ZERO software. I literally had to start from binary machine
    code, as there was no keyboard at first (more below).

    Next you'll tell us you went to the beach and picked up sand so
    you could smelt it and create your own silicon wafers, right?

    You described its capabilities. It was vastly more capable than
    a PDP-7, and it had only one user: you.

    I also never used Algol68; I'd only seen it in a book.

    You said yourself you modeled your language on Algol68; whether
    you had used it or not is irrelevant.

    In my job later I was an engineer, not a programmer, and there was no
    budget for software such as compilers. But they would anyway have been a
    nightmare to install (floppy disk formats were not standard!), and would
    been hopelessly slow to use.

    The language I ended up creating was perfect for my needs and compiled
    more or less instantly.

    You said you could not use a compiler and then literally
    described using a compiler.

    You do know; you just don't want to admit it. (Imagine introducing C
    declarations into a current language.)

    No, really; C's declaration syntax was inspired by FORTRAN, and
    generations of scientists and engineers have managed that
    language just fine.

    FORTRAN syntax looked nothing like C! Unless you mean the general
    pattern of 'INTEGER A, B' which was shared by half of all languages.

    That was literally the thing you said you address with
    left-to-right syntax, and that anyone who proposed such would be
    laughed at. Now it's fine, just not in C. Because C is bad.
    Or something.

    (I spent a year writing FORTRAN on mainframes and minicomputers.)

    I'm sure no one else here has done that. (*rolls eyes*)

    Generations of programmers have handled C's
    all right as well.

    How many gave up because it was too much? How many still struggle with
    it and have to employ those 4 or 5 workarounds which I mention
    elsewhere? How much has it affected productivity?

    Your statement is meaningless. Maybe some task (in any sphere) takes 17
    steps to achieve. People will manage. But then somebody figures out how
    to do it in 3 steps; that's better right?

    Maybe, maybe not. There may well be other considerations that
    factor into that decision.

    No, according to you: let's stick with 17 steps; people have always
    managed, and 10 million people can't be wrong!

    So by this metric, it's cool if a pilot just jumps into an
    airliner, turns it on, and takes off? The rest of the
    pre-flight checklist is just busywork, amirite?

    Then why do you keep bringing your language up, showing snippets
    of its syntax, and so on?

    Suppose that language didn't exist. I guess then it would be OK to bring
    up hypothetical new features and bits of syntax here? People do it all
    the time (even Keith did today, of all people).

    But if those examples come from an actual, working and proven
    implementation, which lend them more weight, then it is not allowed and
    the examples then become irrelevant?

    If you want to discuss C on its merits, then discuss C.
    Unfortunately for you that would probably mean you'd have to
    actually read the relevant documentation.

    Do you _really_ think that the people who post here regularly
    are not aware that, say, other variable declaration syntaxes
    exist that are less messy than C's? No, seriously, don't give
    me some other example from your language, answer that question
    honestly: do you _really_ believe that no one here understands
    that fact, or just outright disbelieves it?

    I guess it is not playing the game in that case?
    Why hasn't there long been an alternative systems language that didn't >>>> have C's crazy syntax and stupid quirks? I mean like 30-50 years ago.

    There...have been? And still are?

    In that case, why has C itself been so heavily used, in OSes, drivers,
    and endless libraries, rather than one those which you suggest I adopt?

    I can think of any number of reasons: legacy, compatibility,
    tool availability, in some cases just personal preference. For
    any one of these, I'm sure that someone has already told you
    sometime in the last six months. My repeating them is unlikely
    to have any effect.

    I needed a language that worked at a lower level, could access hardware,
    had inline assembly, had a weak type system that allowed all sorts of
    underhand methods /to get things done/.
    [snip same stuff over again]

    No one cares.

    [snip]
    I gave you my circumstances above. What would /you/ have done?

    Probably not spent years seething about how the rest of the
    world is wrong for making decisions I would not have.

    [snip]
    That's why ABIs matter.

    You're confusing APIs and ABIs.

    ABIs are a matter for compilers. Translating APIs into a set of bindings
    for another language is someone else's job.

    You really don't understand how multilangauge environments work,
    do you? Maybe have a look at an ABI document at some point.

    [snip sob story about walking uphill both ways in the snow]
    But the crude
    language I created FROM NOTHING still looked like this:

    int a, b, c
    println a + b

    Ok. Don't really care.

    As mentioned, C came from B, once they got a PDP-11; it was an
    incremental evolution of a language they already had. The type
    syntax you find so distasteful was inspired by FORTRAN.

    Please give an example of FORTRAN that looks like C.

    Why? What would that show?

    If you'd get over yourself for ten minutes and read the HOPL
    paper on C, you may see this:

    |Fortran influenced the syntax of declarations: B declarations
    |begin with a specifier like `auto` or `static`, followed by a
    |list of names, and C not only followed this style but
    |ornamented it by placing its type keywords at the start of
    |declarations. (https://www.nokia.com/bell-labs/about/dennis-m-ritchie/chist.html)

    It's so weird to me that you make such absolute pronouncements
    about C and the choices that into its design, but are so
    ajbectly ignorant of the actual history. Bluntly, you just are
    not very well informed about it to make cogent comments.

    How does knowing the history in such detail help? If a feature stinks,
    it stinks.

    Much of your ranting amounts to, "how could anyone have possibly
    thought this was a good idea?" Perhaps if you looked into the
    history a bit, you may become enlightened as to why anybody
    possibly thought it was a good idea.

    See my post yesterday about the impact choosing a prefix dereference op
    instead of postfix made on the language. It was probably even more
    far-reaching than stated.

    And yet Pascal was right there!

    Amazingly, ALGOL W used syntax much closer to C's, despite being
    the immediate predecessor of Pascal.

    That choice had nothing to with limited hardware; it was just the wrong one.

    One final quote from HOPL:
    |Although we entertained occasional thoughts about implementing
    |one of the major languages of the time like Fortran, PL/I, or
    |Algol 68, such a project seemed hopelessly large for our
    |resources: much simpler and smaller tools were called for. All
    |these languages influenced our work, but it was more fun to do
    |things on our own.

    So, they were aware of all the languages you've cited as
    influences. And yet they decided to do things differently.

    Perhaps they had their reasons. They are not (in the case of
    Ken) and were not (sadly, in the case of Dennis) idiiots or
    fools.
    If you're going to shit over everything I say, ignore points and keep
    changing the subject, then OK you win, I lose.

    Satisfied?

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Michael S@[email protected] to comp.lang.c on Mon Oct 19 22:35:38 2026
    From Newsgroup: comp.lang.c

    On Mon, 19 Oct 2026 15:44:40 +0200
    Janis Papanagnou <[email protected]> wrote:

    On 2026-10-18 18:32, Michael S wrote:
    On Sun, 18 Oct 2026 18:11:18 +0200
    Janis Papanagnou <[email protected]> wrote:

    I don't recall to have used any language with infix-expressions
    that would have their monadic operators defined in postfix form.

    I am a Bear of Very Little Brain, and long words Bother Me.

    (If that quote is important for your argument, please explain.)


    Translation:
    1. I have no idea what unary * has to do with infix-expressions
    2. I don't appriciate use of the term "infix-expression" instead of more
    common (in context of description of C and similar languages) term
    'binary operators'.
    3. I don't know what "monadic operators defined in postfix form" means
    and have no plans to look for the meaning

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@[email protected] to comp.lang.c on Mon Oct 19 23:27:03 2026
    From Newsgroup: comp.lang.c

    On 2026-10-19 21:35, Michael S wrote:
    On Mon, 19 Oct 2026 15:44:40 +0200
    Janis Papanagnou <[email protected]> wrote:

    On 2026-10-18 18:32, Michael S wrote:
    On Sun, 18 Oct 2026 18:11:18 +0200
    Janis Papanagnou <[email protected]> wrote:

    I don't recall to have used any language with infix-expressions
    that would have their monadic operators defined in postfix form.

    I am a Bear of Very Little Brain, and long words Bother Me.

    (If that quote is important for your argument, please explain.)


    Translation:
    1. I have no idea what unary * has to do with infix-expressions
    2. I don't appriciate use of the term "infix-expression" instead of more common (in context of description of C and similar languages) term
    'binary operators'.
    3. I don't know what "monadic operators defined in postfix form" means
    and have no plans to look for the meaning


    I'm sorry, these are (AFAICT) common terms, and I thought obvious.
    So let me explain and amend with more text and examples...

    Point 1. - I gave the hint that in languages that support RPN
    (= Reverse Polish Notation) things like monadic postfix operators
    (= having just _one_ argument applied _after_ the operator) are the
    natural way of writing expressions. Less so in languages, which are
    the majority since decades, that support expressions with infix
    operators (= the operator arguments left and right of the operator).

    Point 2. - A "binary operator" may be the '*' in the expressions
    a * b typical infix notation (with parenthesis for precedence)
    a b * RPN
    * a b PN (Polish Notation)

    A "binary operator" is something different from an "infix expression"
    (the first one of the three; the others are RPN and PN examples).
    That's why I took the appropriate term to explain what I intended to
    explain.

    Point 3. - "monadic" (see point 1). Applying to postfix form is best
    explained on another example; assume RPN
    a - monadic (unary) minus (on one argument)
    a b - dyadic (binary) minus (difference of two arguments)

    Hope the terms are clear now. Now consider our original case, e.g.

    a * *b ... multiply and dereference
    a - -b ... subtract and negate

    as soon as we parse the second operator we know its kind. With postfix operators we'd have (assuming same semantics but with postfix operators)

    a * b * ... now what is the second '*' at that point of parsing?
    a - b - ... we don't expect that second '-' to be a negation.

    The compilers can handle every variant. For the users it's different;
    usually they seem to prefer unary operators to be prefixed (YMMV).

    The question (concerning "C") was; would it have been "better" (in any
    respect) if the dereferencing operator would have been defined in "C"
    as postfix operator (as you seem to prefer).

    Janis

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Mon Oct 19 22:28:34 2026
    From Newsgroup: comp.lang.c

    On 19/10/2026 14:46, David Brown wrote:
    On 19/10/2026 15:16, Janis Papanagnou wrote:
    On 2026-10-18 21:09, David Brown wrote:
    On 18/10/2026 18:09, bart wrote:
    [...]
    [ declaration syntax ]

    (I just want to comment on a [not unimportant] detail...)


    You need to give things in the right order, or use parentheses, to
    get the right "type expression".  It's just like any other kind of
    expression.

    The intention of the declaration syntax in C is that the declaration
    order follows usage.  [...]

    I think the first part is downplaying that languages typically indeed
    make a distinction between parenthesized expressions and declarations.
    Quite some other languages [not from the C-heritage] that I used all
    did not need to introduce "expression"-grouping for _declarations_ in
    the first place given their more consistent ways to declare entities.

    The second part is, as I had understood C's history, the idea behind
    how it got defined; needless to say that I think that was a bad idea.
    But that's what we've got! If they had dropped that requirement/idea
    the declaration syntax could have become "better" (more consistent,
    less cryptic, less convoluted, clearer). Now, after half a century,
    we just have to live with that, and folks who have "problems" with it
    should better not touch this language (or maybe not doing programming
    at all). The somewhat tragic aspect is that the "declaration follows
    use" idea was (IIRC) intended to _simplify_ the understanding of its
    concepts and use of the language; the consequences were seemingly not
    valued correctly.

    There are a number of things that I don't particularly like about C's declaration syntax, or where I think it would have been better if it
    were different.  But the "inside-to-outside" ordering is not one of
    them.  That is not because I think it is better or clearer than left-to- right ordering, but because when I compare to, say, Pascal, it's not a
    big issue for me.  Far bigger are :

    1. People put too much into a single type declaration, rather than
    building types out of logical parts with a purpose and a name.  They
    don't do it as much as Bart likes to pretend, but some people do it too
    much for my liking.  The language doesn't force you to do that - it's programmer style.  IMHO there is never a reason for a "pointer to an
    array of function pointers taking int and returning void" - no matter
    what syntax is used.

    Then you have a peculiar and restricted coding style.

    (Funny that when I suggest that nested loop breaks are uncommon,
    everyone says I'm wrong! Some even write 200-line made-up examples to
    prove their point.)

    These are two actual function pointer arrays from my projects (not C):

    []ref proc hosthandlers = ...

    [pclnames.len]ref proc(pcl) px_handlertable

    There is no reason to abstract away that function pointer type.

    You probably do so in C /because/ the type involves * () and [] but have somehow persuaded yourself that it just better that way.

    Note that 'pcl' in my example /is/ a typedef; here it makes sense as it
    is used in 100s of places. This function pointer occurs in only one place.

    (The C version looks like: 'void (*name[N]))T)'. I used a tool and
    transcribed it, then I double-checked and found I'd written '(*name)[N]'
    not '(*name[N])'; I wouldn't have noticed.)

    BTW what name would be given to such a function pointer type? There is
    nothing obvious other than 'funcptr', but suppose there is more than one
    in scope?

    Something else strikes me about breaking up a complex type-decl sequence
    into a chain of typedefs: if you take that list of typedefs, and rotate
    it 90 degrees c/w, you have something that resembles the LTR representation!


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@[email protected] to comp.lang.c on Mon Oct 19 23:29:54 2026
    From Newsgroup: comp.lang.c

    Darn typo...

    On 2026-10-19 23:27, Janis Papanagnou wrote:
    Point 1. - I gave the hint that in languages that support RPN
    (= Reverse Polish Notation) things like monadic postfix operators
    (= having just _one_ argument applied _after_ the operator) are the

    (= having just _one_ argument and operator applied _after_ the argument)

    Janis


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Michael S@[email protected] to comp.lang.c on Tue Oct 20 00:57:20 2026
    From Newsgroup: comp.lang.c

    On Mon, 19 Oct 2026 23:27:03 +0200
    Janis Papanagnou <[email protected]> wrote:

    On 2026-10-19 21:35, Michael S wrote:
    On Mon, 19 Oct 2026 15:44:40 +0200
    Janis Papanagnou <[email protected]> wrote:

    On 2026-10-18 18:32, Michael S wrote:
    On Sun, 18 Oct 2026 18:11:18 +0200
    Janis Papanagnou <[email protected]> wrote:

    I don't recall to have used any language with infix-expressions
    that would have their monadic operators defined in postfix form.


    I am a Bear of Very Little Brain, and long words Bother Me.

    (If that quote is important for your argument, please explain.)


    Translation:
    1. I have no idea what unary * has to do with infix-expressions
    2. I don't appriciate use of the term "infix-expression" instead of
    more common (in context of description of C and similar languages)
    term 'binary operators'.
    3. I don't know what "monadic operators defined in postfix form"
    means and have no plans to look for the meaning


    I'm sorry, these are (AFAICT) common terms, and I thought obvious.
    So let me explain and amend with more text and examples...

    Point 1. - I gave the hint that in languages that support RPN
    (= Reverse Polish Notation) things like monadic postfix operators
    (= having just _one_ argument applied _after_ the operator) are the
    natural way of writing expressions. Less so in languages, which are
    the majority since decades, that support expressions with infix
    operators (= the operator arguments left and right of the operator).

    Point 2. - A "binary operator" may be the '*' in the expressions
    a * b typical infix notation (with parenthesis for precedence)
    a b * RPN
    * a b PN (Polish Notation)

    A "binary operator" is something different from an "infix expression"
    (the first one of the three; the others are RPN and PN examples).
    That's why I took the appropriate term to explain what I intended to
    explain.


    O.k.

    Point 3. - "monadic" (see point 1). Applying to postfix form is best explained on another example; assume RPN
    a - monadic (unary) minus (on one argument)
    a b - dyadic (binary) minus (difference of two arguments)

    Hope the terms are clear now. Now consider our original case, e.g.

    a * *b ... multiply and dereference
    a - -b ... subtract and negate

    as soon as we parse the second operator we know its kind. With postfix operators we'd have (assuming same semantics but with postfix
    operators)

    a * b * ... now what is the second '*' at that point of parsing?

    If C was as strongly typed from the beginning as it ended up in the 2nd
    half of the 70s then it would make sense to use postfix . (dot) instead
    of prefix * as dereference operator.
    Unfortunately, in early stage of development C was almost untyped, so
    something like that was out of question.

    a - b - ... we don't expect that second '-' to be a negation.

    The compilers can handle every variant. For the users it's different;
    usually they seem to prefer unary operators to be prefixed (YMMV).

    The question (concerning "C") was; would it have been "better" (in any respect) if the dereferencing operator would have been defined in "C"
    as postfix operator (as you seem to prefer).

    Janis


    It would be certainly better in the context of type declarators. By now
    mixing postfix with prefix is their most confusing part.
    I have no strong opinion about advantages and disadvantages of postfix
    in context of use of * in expressions, but suspect that in this context
    the postfix will slightly reduce the need for parenthesis.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@[email protected] to comp.lang.c on Mon Oct 19 15:28:07 2026
    From Newsgroup: comp.lang.c

    David Brown <[email protected]> writes:
    On 19/10/2026 12:50, Keith Thompson wrote:
    [...]
    The odd scoping rules for labels don't bother me either. They mean
    you can't have two loops or switch statements with the same name in
    the same function. I can barely imagine that being inconvenient.

    I can imagine that being a bit inconvenient in some cases, but I think
    the proposal in N3658 would simply and cleanly fix that.
    [...]

    *If* the fact that labels (which are now also loop/switch names)
    follow strange scope rules is a real problem, N3658 is probably
    the best practical solution. I'm slightly uncomfortable with the
    idea of an entity's scope depending on how it's used, not just how
    it's defined. I think it introduces a complication to the language
    without much real benefit.

    But cleaner solutions are impractical.

    IMHO the only really clean solution would be to make labels and
    loop/switch names distinct, keep the existing scoping rules for
    labels, and use more normal scoping rules for loop/switch names.
    And if the "while NAME (...)" proposal were accepted, that's probably
    how it should work. (But I prefer having the name as a prefix of the
    loop or switch statement.)

    If N3658 were adopted, it wouldn't bother me much. I just don't
    think it's necessary.
    --
    Keith Thompson (The_Other_Keith) [email protected]
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@[email protected] to comp.lang.c on Tue Oct 20 00:35:12 2026
    From Newsgroup: comp.lang.c

    On 2026-10-19 19:22, Dan Cross wrote:
    In article <11b500f$216c4$[email protected]>, bart <[email protected]> wrote:
    [...]
    I also never used Algol68; I'd only seen it in a book.

    You said yourself you modeled your language on Algol68; whether
    you had used it or not is irrelevant.

    It may be worth the observation we could make here in the flood of
    bart's posts; most (if not all) features or ideas he seems to have
    adopted only on a lexical or syntactical level. Given what he gave
    as examples I have strong doubts that this should be attributed to
    Algol 68 in its "whole glory". - Syntactical inspiration; maybe. -
    More than that? - I'd be astonished.

    [...]

    One final quote from HOPL:
    |Although we entertained occasional thoughts about implementing
    |one of the major languages of the time like Fortran, PL/I, or
    |Algol 68, such a project seemed hopelessly large for our
    |resources: much simpler and smaller tools were called for. All
    |these languages influenced our work, but it was more fun to do
    |things on our own.

    So, they were aware of all the languages you've cited as
    influences. And yet they decided to do things differently.

    Somewhere in a (meanwhile historic; 1990's?) document I read about
    someone (D.R.?) say that the influence of Algol 68 would be hardly
    seen in practice (or some such). - It's generally hard to tell if
    someone adopted concepts from some another specific language or
    read the language description to just dismiss all their ideas. ;-)
    In case of "C" and Algol 68, while I indeed see a couple adopted
    things, they are so rare, lacking the semantic context, or have
    been realized in a very stripped down variant, that it's hard to
    speak about being (in a more substantial way) "influenced" by it.

    To not stress my brain unnecessarily here's what a search suggests:
    Type Composition, Unions and Casts, Syntax and Operators, and Type
    Names & Structure. (I could add a few more, but I'd keep it terse.)

    Type Compositions: fine, but also no rocket science back then.
    Unions: a completely different concept in "C".
    Casts: hardly necessary in Algol 68 (primarily used for references).
    Syntax: beyond block structure, a completely different thing in "C".
    Operators: Not comparable in many respects.
    Type Names: 'bool', 'string', 'complex', etc., in original "C"? No.

    So I agree with the mentioned paper that it's hard to find this
    Algol 68 inspiration in "C"; and certainly not as a characterizing
    property of the language. With knowledge and a sharp eye you just
    find some (often only faint) traces as remains (that might as well
    have had another origin in some cases as we may infer from the list).

    Janis

    [...]

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@[email protected] to comp.lang.c on Mon Oct 19 15:48:16 2026
    From Newsgroup: comp.lang.c

    Janis Papanagnou <[email protected]> writes:
    On 2026-10-18 21:09, David Brown wrote:
    On 18/10/2026 18:09, bart wrote:
    [...]
    [ declaration syntax ]

    (I just want to comment on a [not unimportant] detail...)

    You need to give things in the right order, or use parentheses, to
    get the right "type expression".  It's just like any other kind of
    expression.
    The intention of the declaration syntax in C is that the declaration
    order follows usage.  [...]

    I think the first part is downplaying that languages typically indeed
    make a distinction between parenthesized expressions and declarations.
    Quite some other languages [not from the C-heritage] that I used all
    did not need to introduce "expression"-grouping for _declarations_ in
    the first place given their more consistent ways to declare entities.

    Just one quibble. C's declaration syntax *is* consistent. Its
    rules are rigorously specified by the standard, particularly by
    the grammar.

    Many of us (myself included) don't particularly like it, but that
    doesn't mean it's inconsistent.

    My own take on all this is that having declaration syntax follow usage
    was a very clever idea, where "clever" is not necessarily a compliment.
    It was IMHO unsuccessful in the sense that it can lead to confusing
    and overly complicated declarations. (Other languages don't have tools corresponding to cdecl for much the same reason that Spanish-speaking
    countries don't have spelling bees.) But it was extraordinarily
    successful in the sense that, even if you think it was a bad idea,
    it wasn't bad enough to keep C from becoming one of the most popular programming languages.

    (I wonder if keeping the declaration-follows-use principle while
    making "*" a postfix operator might have improved things.)
    --
    Keith Thompson (The_Other_Keith) [email protected]
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@[email protected] to comp.lang.c on Tue Oct 20 00:55:11 2026
    From Newsgroup: comp.lang.c

    On 2026-10-19 23:57, Michael S wrote:
    On Mon, 19 Oct 2026 23:27:03 +0200
    Janis Papanagnou <[email protected]> wrote:
    [...]

    If C was as strongly typed from the beginning as it ended up in the 2nd
    half of the 70s then it would make sense to use postfix . (dot) instead
    of prefix * as dereference operator.

    Well, in "C" we have (for pointers) at least "p->v" as shortcut of
    "(*p).v" which is good to have! But that '->' is a dyadic operator
    and makes (for this specific case) the deref operator unnecessary.

    We still need it for other purposes, like the often cited "*a++ = *b++".
    I don't see how the situation would have been different in the 1970's,
    though. But nevermind.

    (Other languages might not even impose the differentiation and just
    have "p.v" and "s.v" for both, access of components referenced by
    pointer or direct struct access. Yet other languages do any 'deref' implicitly.)

    Janis

    [...]

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Tue Oct 20 00:04:53 2026
    From Newsgroup: comp.lang.c

    On 19/10/2026 23:35, Janis Papanagnou wrote:
    On 2026-10-19 19:22, Dan Cross wrote:
    In article <11b500f$216c4$[email protected]>, bart  <[email protected]> wrote:
    [...]
    I also never used Algol68; I'd only seen it in a book.

    You said yourself you modeled your language on Algol68; whether
    you had used it or not is irrelevant.

    It may be worth the observation we could make here in the flood of
    bart's posts; most (if not all) features or ideas he seems to have
    adopted only on a lexical or syntactical level. Given what he gave
    as examples I have strong doubts that this should be attributed to
    Algol 68 in its "whole glory". - Syntactical inspiration; maybe. -
    More than that? - I'd be astonished.

    Syntax was part-influenced by Algol 60 (DEC), Algol 68, Pascal, Fortran
    and Ada. It was also case-insensitive (most of them). And
    expression-based (Algol 68).

    Type system and semantics were mine and befitted a low level systems
    language running on and for very low-end hardware.



    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@[email protected] to comp.lang.c on Mon Oct 19 16:11:46 2026
    From Newsgroup: comp.lang.c

    Tim Rentsch <[email protected]> writes:
    Janis Papanagnou <[email protected]> writes:
    On 2026-10-18 12:48, David Brown wrote:
    On 17/10/2026 01:29, Janis Papanagnou wrote:
    On 2026-10-17 00:00, Keith Thompson wrote:
    Tim Rentsch <[email protected]> writes:
    Keith Thompson <[email protected]> writes:
    [...]
    There's a proposal for C2y to use goto labels as loop names, and a >>>>>>> competing one to define a new syntax like "for NAME (;;)" :
    [...]

    I'm not particularly a fan of multi-level break/continue. But if
    we're going to have one of these, the second ("for NAME (;;)") is
    unquestionably better.

    Unquestionably? Why?

    Why would one question an opinion? ;-)

    Time didn't word it as a personal opinion - he made it clear that he
    doesn't think anyone else could have a different opinion.

    You've noticed my smiley? (There was no need for an explanation.)

    Anyone who thinks my statement "the second ("for NAME (;;)") is unquestionably better" was meant as a statement of fact rather
    than a statement of opinion is an idiot.

    "Better" is an opinion, and if you had just said that I wouldn't have
    replied.

    If you're saying that "unquestionably better" is merely an opinion,
    I now accept that you meant it that way, but that's not the way I
    interpreted it. It implies, not merely that something is better,
    but that nobody could possibly question that it's better. I suggest
    you write more clearly rather than insulting your readers, perhaps
    by choosing a word other than "unquesionably" to denote emphasis.

    When I asked you to explain, you responded by giving me a detailed
    homework assignment as a prerequisite to answering my question.
    Perhaps you weren't serious about that, but I couldn't tell.

    To be clear, I am no longer asking you to explain what you meant by "unquestionably better".

    I think most people can see that I am careful in my writing, and
    also that I make an effort to differentiate statements of opinion,
    statements of belief, and statements of fact. My remark above is
    no exception to that practice.

    Apparently you didn't *intend* it to be an exception to that practice.

    For the benefit of any other people who may have not seen the
    distinction here, please remember this: any statement that uses
    the word "better", when made without any reference to some sort of
    objective metric, is inherently a subjective statement. Any
    subjective statement (that does not fall into the category of
    being a statement of belief) is a statement of opinion. It's easy
    to see this simply by a process of elimination, because subjective
    statements are not facts, and vice versa.

    <sarcasm>Thank you for explaining that to us.</sarcasm>

    You used the phrase "unquestionably better". I questioned that. If
    your problem with my response was that you were merely expressing
    an opinion, you could have just said that rather than wasting our
    time by bloviating about the difference between opinions and facts.

    [...]

    My confidence in the collective wisdom of the ISO C committee has
    declined in recent years, and sadly for more than just the last
    few years. So learning that they have settled (even if that might
    change in the future) on the "label: for(...)" approach is
    disappointing, but not surprising.

    I acknowledge your opinion. I certainly do not share it.
    --
    Keith Thompson (The_Other_Keith) [email protected]
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@[email protected] to comp.lang.c on Tue Oct 20 01:18:46 2026
    From Newsgroup: comp.lang.c

    On 2026-10-20 00:48, Keith Thompson wrote:
    Janis Papanagnou <[email protected]> writes:
    On 2026-10-18 21:09, David Brown wrote:
    On 18/10/2026 18:09, bart wrote:
    [...]
    [ declaration syntax ]

    (I just want to comment on a [not unimportant] detail...)

    You need to give things in the right order, or use parentheses, to
    get the right "type expression".  It's just like any other kind of
    expression.
    The intention of the declaration syntax in C is that the declaration
    order follows usage.  [...]

    I think the first part is downplaying that languages typically indeed
    make a distinction between parenthesized expressions and declarations.
    Quite some other languages [not from the C-heritage] that I used all
    did not need to introduce "expression"-grouping for _declarations_ in
    the first place given their more consistent ways to declare entities.

    Just one quibble. C's declaration syntax *is* consistent. Its
    rules are rigorously specified by the standard, particularly by
    the grammar.

    Yes, sure. It's well defined and all that. - What I tried to express
    by that is that the building rules are not... - coherent, consistent?
    Well, I think on that level speaking about "inconsistency" is fine.
    But okay. I think we all know what we have with C's declaration syntax.
    (And we all, but maybe one, can live with it.)


    Many of us (myself included) don't particularly like it, but that
    doesn't mean it's inconsistent.

    My own take on all this is that having declaration syntax follow usage
    was a very clever idea, where "clever" is not necessarily a compliment.

    Well, to return the quibble, clever is a compliment (while "clever"
    in quotes is obviously not). :-)

    I don't consider it to have been a clever idea. (No quotes.) But I
    had mentioned that elsethread already before, and it's IMO not worth
    a dispute.

    It was IMHO unsuccessful in the sense that it can lead to confusing
    and overly complicated declarations.

    And that's the essence of the criticism, I think.

    (Other languages don't have tools
    corresponding to cdecl for much the same reason that Spanish-speaking countries don't have spelling bees.) But it was extraordinarily
    successful in the sense that, even if you think it was a bad idea,
    it wasn't bad enough to keep C from becoming one of the most popular programming languages.

    Undoubtedly. (It wasn't bad enough.) - Now imagine if it were better!
    Would have all folks using - what-do-I-know, say, Java - then have
    settled with "C"? - I'm just kidding.


    (I wonder if keeping the declaration-follows-use principle while
    making "*" a postfix operator might have improved things.)

    I'm confused about the recent emphasis of such a change; it very much
    sounds to me like: "we have a problem lets try fixing it by changing
    something else [instead of addressing the problem]"; both are useless
    thoughts. (Yes, I understand that you think about it academically.)

    Janis

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Bob Duff@[email protected] to comp.lang.c on Mon Oct 19 19:38:38 2026
    From Newsgroup: comp.lang.c

    Keith Thompson <[email protected]> writes:

    Names used for loops have a lighter-weight syntax:

    LOOP_NAME:
    while condition loop
    -- ...
    end loop;

    That's a syntax error. In Ada, if you put a loop name at the top of the
    loop, you are required to repeat it at the bottom, like this:

    LOOP_NAME: while condition loop
    ...
    end loop LOOP_NAME;

    If there's an "exit LOOP_NAME;" in there, it's pretty clear which
    loop it's jumping out of, AND where it's jumping to.

    I can't think of a better syntax for loop names than "NAME:" (used
    by several other languages), but in C that syntax is already
    taken for goto labels.

    Agreed.

    But in current C (before adding the named-loop feature),
    and in Ada, and in many other languages, a label serves
    as a warning: One or more gotos jump here. That's useful
    information.

    This new feature of C seems to lose that benefit, which
    is unfortunate. But I think the "while LOOP_NAME..."
    syntax is less readable than "LOOP_NAME: while...",
    as you said.

    So if it were up to me, I wouldn't add named loops to C in
    either proposed syntax. The "goto" is good enough for
    jumping out of nested loops.

    - Bob
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Kaz Kylheku@[email protected] to comp.lang.c on Mon Oct 19 23:41:30 2026
    From Newsgroup: comp.lang.c

    On 2026-10-16, Keith Thompson <[email protected]> wrote:
    Tim Rentsch <[email protected]> writes:
    Keith Thompson <[email protected]> writes:
    I find "break NAME;", where "NAME" is the name of an enclosing
    construct, unambiguously better than "break N;", where N is the
    number of levels to break out of. [...]

    Definitely.

    There's a proposal for C2y to use goto labels as loop names, and a
    competing one to define a new syntax like "for NAME (;;)" :

    https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3355.htm
    https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3377.pdf

    I'm not particularly a fan of multi-level break/continue. But if
    we're going to have one of these, the second ("for NAME (;;)") is
    unquestionably better.

    Unquestionably? Why?

    I do like the fact that it doesn't conflate goto labels with loop
    names, but I still prefer the "NAME: for (;;)" form, partly because
    it's consistent with several other languages.

    If a loop has a statement label, traditionally usable with goto,
    and we allow it to be used with a break, that is still a "goto label".

    The break is a kind of goto, and the named break is a goto-like transfer
    whose target is found with the help of the label, just a little
    differently from goto. It goes past the labeled statement, essentially.

    It's a "goto-adjacent operation" or "close sibling of goto".

    It could be generalized such that if there is a labelled statement
    "L: S" in the function scope, then "break X" anywhere in the function
    can be used anywhere in the function to jump to that abstract point
    where control ends up immediately after the execution of S.

    In other words, supposed things were as if L: S had the meaning
    L: { S; __L_after :; } and "break L;" with a label argument then
    has the meaning "goto __L_after". Except that there is no such
    code transformation; the target of "break L" is an abstract point
    relatie to the statement labeleld by L without any invisible
    auxilirary derived label.

    Then there would be complete consistency: the scope of L would be
    the same regardless of whether it is used as a break or goto target,
    and L would be acting as a control transfer destination in both
    uses, disparaging all traces of a conflation.

    Now imagine that we have this design and we don't like that
    a break can transfer past a labelled statement from anywhere
    in a function.

    We can then add the constraint that a "break L" statement is
    required to be located inside the statement labelled by L.

    That does not change the scope; it's just a constraint. A "break L"
    outside of that statement is understood perfectly well as referring to unambiguously that L, but required to be diagnosed. (Could be readily
    supported as an extension.)
    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @[email protected]
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@[email protected] to comp.lang.c on Mon Oct 19 17:03:30 2026
    From Newsgroup: comp.lang.c

    Bob Duff <[email protected]> writes:
    Keith Thompson <[email protected]> writes:
    Names used for loops have a lighter-weight syntax:

    LOOP_NAME:
    while condition loop
    -- ...
    end loop;

    That's a syntax error. In Ada, if you put a loop name at the top of the
    loop, you are required to repeat it at the bottom, like this:

    LOOP_NAME: while condition loop
    ...
    end loop LOOP_NAME;

    Right, I forgot that. It's also a syntax error because there are no
    statements in the body of the loop, just a comment.

    If there's an "exit LOOP_NAME;" in there, it's pretty clear which
    loop it's jumping out of, AND where it's jumping to.

    Yes.

    I can't think of a better syntax for loop names than "NAME:" (used
    by several other languages), but in C that syntax is already
    taken for goto labels.

    Agreed.

    But in current C (before adding the named-loop feature),
    and in Ada, and in many other languages, a label serves
    as a warning: One or more gotos jump here. That's useful
    information.

    Well, zero or more gotos, but yes.

    This new feature of C seems to lose that benefit, which
    is unfortunate. But I think the "while LOOP_NAME..."
    syntax is less readable than "LOOP_NAME: while...",
    as you said.

    Agreed -- but you can always search a function body for occurrences
    of "goto". If a function is big enough to make that difficult,
    either it's machine-generated or you should probably rethink your
    program structure.

    Once the new feature is widely available, I think that the fact that
    a label is at the top of a loop or switch statement is a strong clue
    that it's *not* the target of a goto.

    So if it were up to me, I wouldn't add named loops to C in
    either proposed syntax. The "goto" is good enough for
    jumping out of nested loops.

    I commonly use named loops in Perl -- and in a recent search through
    a bunch of my Perl code, I found that I typically *don't* use it as
    a way to break out of a nested loop. I find that giving a name to a
    loop can make the code easier to understand: this loop iterates over command-line arguments, that one iterates over lines in a file. (Perl
    uses the same syntax for goto labels and loop names. I don't think
    I've ever used goto in Perl outside small throwaway test scripts.)
    --
    Keith Thompson (The_Other_Keith) [email protected]
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From antispam@[email protected] (Waldek Hebisch) to comp.lang.c on Tue Oct 20 00:16:21 2026
    From Newsgroup: comp.lang.c

    Tim Rentsch <[email protected]> wrote:
    [email protected] (Waldek Hebisch) writes:

    Lawrence D?Oliveiro <[email protected]d> wrote:

    On Tue, 13 Oct 2026 07:23:40 -0000 (UTC), Waldek Hebisch wrote:

    So what those counts indicate: majority of loops is simple, that is
    have no early exit. Vast majority of early exits is done via
    'return'.

    My experience in my own C code is quite the opposite. Lots of loops
    have exits in the middle, leading me to use forms like ?for (;;)?. I
    also try to avoid putting ?return? anywhere other than the end of a
    function, to make it easier to see the flow of control.

    Well, usually there is a lot of loops. Those with exit in the
    middle are still significant.

    Concernig 'return', having it in place where all work inside function
    is done help me to see flow control and avoids complications. In
    case of search functions it means return from the middle of the loop.
    IMO possible alternatives like flag variables or break and retrun
    after loop are worse.

    I rarely use 'break' to exit a loop. Part of this is that I try to
    write standard loops so that they complete as part of the loop test
    (i.e., in while() or for() control expressions). That isn't the
    whole story though so let me talk about 'return'.

    I counted various constructs in a small suite of 2 programs (1306
    lines in 3 files). There are 4 breaks outside switches and 32
    loops in total. My gut feeling is that this proportion is
    reasonable close to typical in my code. For comparison, there
    are 67 functions and 70 'if'-s.

    Most of the functions I write have exactly one return, at the end of
    the function. I estimate this pattern accounts for around 85% of
    all functions, let's say plus or minus 5%.

    In code above about half of functions is 'void' and there are 34
    explicit returns (of which at least 2 are early returns).

    Sometimes functions have early returns for errors or exceptional
    conditions.

    Code above contains 16 occurences of 'exit(1)'. One of those is
    in a macro that is used 10 times, so actually there are 25 places
    which call 'exit(1)'. That is related to the programs being
    simple utilities, there is no attempt to error recovery, on error
    programs simply print error message and exit.

    Early returns are easily seen to lie outside the main
    body of function processing so they don't interfere with
    understanding what the rest of the function is doing or how it
    works.

    A fairly common sub-pattern are functions most of whose body is a
    switch() statement, with all of the switch() cases being a simple
    return.

    Code above has 2 switches, both are in parsing functions, where
    cases either move to next state or signal error. Parsing functions
    also open file and close it when finished and return data structure
    with parsed info.

    It does sometimes happen that a function will have a loop with a
    return in the middle, and also a return at the end for what to do if
    the loop terminates. To me having an in-loop return looks better
    than using an assignment and a break.

    A fairly rare but important pattern is what I might call vectoring
    or decomposition. Here the function body serves to distinguish and
    separate out different regimes of subprocessing. To continue
    processing in a particular regime, a return is used not to directly
    yield a value but rather to call a further function to handle that sub-domain. The benefit here is both to keep function bodies small
    and to allow re-use of commonly called sub-functions.

    Two aspects are important for having these different styles work
    together. One is that it's easy to distinguish the different kinds
    of patterns, and by far the most simple pattern is the most common.
    The other is to be sure to keep function bodies small. Keeping
    function bodies small goes a long way in making them easy to
    understand, which obviously is a key property in writing good code.
    Also keeping function bodies small effectively prevents mixing
    different styles in a single function, serving to reinforce point
    one.

    I think that in general my C code has similar characteristics. But
    let me note that while I have a lot of small functions, I also have
    some which are bigger. I suspect that 10% or more of my code is
    in functions that are bigger then 30 lines. Such functions
    frequently have several variables and there is setup stage to
    initialize things, actual processing and final part (cleanups,
    possibly extraction of result). Stages are clearly sepatated
    by their position inside function, OTOH are strongly coupled due
    to use of variables. My feeling here is that in case of strongly
    coupled code with no reusable parts keeping it inside single
    function is more managable than trying to split it into smaller
    functions.
    --
    Waldek Hebisch
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@[email protected] (Dan Cross) to comp.lang.c on Tue Oct 20 01:02:04 2026
    From Newsgroup: comp.lang.c

    In article <[email protected]>,
    Tim Rentsch <[email protected]> wrote:
    [snip]
    Anyone who thinks my statement "the second ("for NAME (;;)") is >unquestionably better" was meant as a statement of fact rather
    than a statement of opinion is an idiot.

    Yeah? Well, that's just, like, your opinion, man.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From antispam@[email protected] (Waldek Hebisch) to comp.lang.c on Tue Oct 20 01:03:15 2026
    From Newsgroup: comp.lang.c

    bart <[email protected]> wrote:

    OK. But they HAD to create C? There were quite a few languages in the
    early 70s too: like Pascal, Fortran, PL/I, Coral-66, plus of course BCPL
    and B. So why a new one?

    You ignore fact that Ritche wanted reasonably fast code from
    very simple compiler. Around 1970 that meant in particular
    pointer arithmetic. Also, address operator allowed simple
    interfacing between pointer-oriented code and use of variables.
    It is hard to imagine getting similar effect with different
    semantics. IIUC C was not the only language going in this
    direction, but mainstream languages were different.

    Concerning specific languages, there was FORTRAN 66, it had 'do'
    loop as only structured control structure, there rest of control
    was via gotos. And the only data structure were array. Without
    extentions FORTRAN 66 was unsuitable for system work, and arguably
    for non-numeric work even early C was nicer than FORTRAN 66.
    For reasonable speed FORTRAN 66 needed an optimizer which led
    to compiler too big to run on a small machine.

    PL/I had most needed features. But PL/I was a big language,
    to run on small machine they would have to take tiny subset
    and then add extentions. Basicaly they would end up with a
    language which is very far from PL/I.

    Similarly, BCPL was too complicated, B and C were simplifications
    and adaptations small machine.

    I think that Pascal was too late: nominally it was created earlier
    but I think that it was available to Bell Labs only after they
    did initial work leading to C. And Pascal shared problem of
    speed on small machines. Note that later UCSD Pascal which
    run on micros compiled to interpreted bytecode, which significantly
    reduced performance.

    FORTRAN syntax looked nothing like C! Unless you mean the general
    pattern of 'INTEGER A, B' which was shared by half of all languages.

    I think more pattern of

    INTEGER A(20), B

    which has similar structure to C variable declarations. Of course,
    FORTRAN had no pointers (and structures or unions), so Ritche had
    to invent syntax for them.

    IMO C suffers because typedef was added late in the game and
    function prototypes are much later. Prototypes need types and
    to get it one needs "hole" in variable declaration. Where the
    hole should be is specified by the C syntax, but placement of
    hole is probably least clear aspect of declarations.

    IMO C declaration syntax was a mistake, but as real life shows
    it was not a fatal mistake, people can adapt. Note that in
    eighties C position among system languages was not as strong as
    it is now. In particular there were quite decent Modula 2
    compilers and ony many machines Pascal was competitive too.
    But there were no mass migration from C to other languages.
    In fact C was gaining use and other languages lost their position.
    --
    Waldek Hebisch
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@[email protected] to comp.lang.c on Tue Oct 20 02:40:31 2026
    From Newsgroup: comp.lang.c

    On Mon, 19 Oct 2026 08:46:58 -0000 (UTC), Waldek Hebisch wrote:

    You do not win in the market by making easy switch from your product
    to competitor product. You may want to make it easy to switch _to_
    your product. But you want to make switching to competing products
    as hard as possible.

    “Vendor lock-in” -- that’s the old proprietary-software model.
    Customers are growing savvy to that sort of trick, which is why
    open-source software has become so popular.

    The most insidious form isn’t so much about the software, but about
    the proprietary data formats. If competitors’ software cannot read
    files containing the customers’ precious data accumulated over years
    of using a product, then the customer cannot switch to the competitor,
    even if they wanted to.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@[email protected] to comp.lang.c on Tue Oct 20 02:44:18 2026
    From Newsgroup: comp.lang.c

    On Tue, 20 Oct 2026 01:03:15 -0000 (UTC), Waldek Hebisch wrote:

    Similarly, BCPL was too complicated, B and C were simplifications
    and adaptations small machine.

    BCPL was a very bare-bones language -- it didn’t even have structs, or
    even much in the way of types. Every variable was an “integer”. Naming
    the variable didn’t return its value, but its address; you had to use
    an explicit “dereference” operator to get the variable value.

    C was certainly a more complicated language than BCPL.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@[email protected] to comp.lang.c on Tue Oct 20 02:45:47 2026
    From Newsgroup: comp.lang.c

    On Mon, 19 Oct 2026 19:38:38 -0400, Bob Duff wrote:

    The "goto" is good enough for jumping out of nested loops.

    “Goto” leads inevitably to spaghetti code.

    Yes, we see that happening in the real world, all the time.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@[email protected] to comp.lang.c on Tue Oct 20 05:01:21 2026
    From Newsgroup: comp.lang.c

    On 2026-10-20 04:45, Lawrence D’Oliveiro wrote:
    On Mon, 19 Oct 2026 19:38:38 -0400, Bob Duff wrote:

    The "goto" is good enough for jumping out of nested loops.

    “Goto” leads inevitably to spaghetti code. [...]

    Not if you only use it in those rare cases to jump out of a loop
    and in a local context. - A 'break' LABEL is not better or worse
    than a 'goto' LABEL concerning an inherent "spaghetti structure".

    Janis

    PS: "inevitably" - yet another word of type like "unquestionably"
    (that we recently heard in another context). - Careful with adverbs,
    folks, especially with absolute ones in generalizing text contexts!

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@[email protected] to comp.lang.c on Tue Oct 20 09:05:42 2026
    From Newsgroup: comp.lang.c

    On 20/10/2026 00:28, Keith Thompson wrote:
    David Brown <[email protected]> writes:
    On 19/10/2026 12:50, Keith Thompson wrote:
    [...]
    The odd scoping rules for labels don't bother me either. They mean
    you can't have two loops or switch statements with the same name in
    the same function. I can barely imagine that being inconvenient.

    I can imagine that being a bit inconvenient in some cases, but I think
    the proposal in N3658 would simply and cleanly fix that.
    [...]

    *If* the fact that labels (which are now also loop/switch names)
    follow strange scope rules is a real problem, N3658 is probably
    the best practical solution. I'm slightly uncomfortable with the
    idea of an entity's scope depending on how it's used, not just how
    it's defined. I think it introduces a complication to the language
    without much real benefit.

    I can understand the feeling here - it would mean "L1: ; L1: ;" is fine
    until you also add "goto L1;". But it is simply saying that the real
    problem is not duplicate labels - it is ambiguity in the target label.


    But cleaner solutions are impractical.

    I think that is correct.


    IMHO the only really clean solution would be to make labels and
    loop/switch names distinct, keep the existing scoping rules for
    labels, and use more normal scoping rules for loop/switch names.
    And if the "while NAME (...)" proposal were accepted, that's probably
    how it should work. (But I prefer having the name as a prefix of the
    loop or switch statement.)

    We cannot have an ideal solution here - there are always compromises
    when new features are added to existing languages.


    If N3658 were adopted, it wouldn't bother me much. I just don't
    think it's necessary.


    I do see benefits to it. I don't think it will make much difference to
    code in practice - after all, the great majority of functions in C do
    not have any labels, any gotos, or any use of multi-level breaks. But
    it conveniently negates one of the big disadvantages of the prefix label syntax for named control structures. There are code bases where there
    are macros containing loops that might benefit from this, and I can
    imagine it being helpful for generated C code (which is sometimes label-heavy).




    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@[email protected] to comp.lang.c on Tue Oct 20 09:18:29 2026
    From Newsgroup: comp.lang.c

    On 19/10/2026 17:47, Tim Rentsch wrote:
    Janis Papanagnou <[email protected]> writes:

    On 2026-10-18 12:48, David Brown wrote:

    On 17/10/2026 01:29, Janis Papanagnou wrote:

    On 2026-10-17 00:00, Keith Thompson wrote:

    Tim Rentsch <[email protected]> writes:

    Keith Thompson <[email protected]> writes:
    [...]

    There's a proposal for C2y to use goto labels as loop names, and a >>>>>>> competing one to define a new syntax like "for NAME (;;)" :
    [...]

    I'm not particularly a fan of multi-level break/continue. But if
    we're going to have one of these, the second ("for NAME (;;)") is
    unquestionably better.

    Unquestionably? Why?

    Why would one question an opinion? ;-)

    Time didn't word it as a personal opinion - he made it clear that he
    doesn't think anyone else could have a different opinion.

    You've noticed my smiley? (There was no need for an explanation.)

    Anyone who thinks my statement "the second ("for NAME (;;)") is unquestionably better" was meant as a statement of fact rather
    than a statement of opinion is an idiot.

    I, for one, read what you /wrote/ - not what you later claim you meant.


    I think most people can see that I am careful in my writing, and
    also that I make an effort to differentiate statements of opinion,
    statements of belief, and statements of fact. My remark above is
    no exception to that practice.


    I think most people can see that you are /usually/ careful in your
    writing. But you also occasionally make mistakes in the content of your posts, and you regularly totally misjudge how your posts and your
    wording comes across. One thing we know for sure is that you are
    extremely reticent about admitting to being wrong, or that you worded a
    post badly.

    But what do I know? You branded me an "idiot" long ago - ironically
    because I wrote opinions that were worded as though I believed they were facts.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@[email protected] to comp.lang.c on Tue Oct 20 00:45:35 2026
    From Newsgroup: comp.lang.c

    Janis Papanagnou <[email protected]> writes:
    [...]
    Careful with adverbs, folks, especially with absolute ones in
    generalizing text contexts!

    Absolutely!
    --
    Keith Thompson (The_Other_Keith) [email protected]
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@[email protected] to comp.lang.c on Tue Oct 20 10:01:28 2026
    From Newsgroup: comp.lang.c

    On 19/10/2026 23:28, bart wrote:
    On 19/10/2026 14:46, David Brown wrote:
    On 19/10/2026 15:16, Janis Papanagnou wrote:
    On 2026-10-18 21:09, David Brown wrote:
    On 18/10/2026 18:09, bart wrote:
    [...]
    [ declaration syntax ]

    (I just want to comment on a [not unimportant] detail...)


    You need to give things in the right order, or use parentheses, to
    get the right "type expression".  It's just like any other kind of
    expression.

    The intention of the declaration syntax in C is that the declaration
    order follows usage.  [...]

    I think the first part is downplaying that languages typically indeed
    make a distinction between parenthesized expressions and declarations.
    Quite some other languages [not from the C-heritage] that I used all
    did not need to introduce "expression"-grouping for _declarations_ in
    the first place given their more consistent ways to declare entities.

    The second part is, as I had understood C's history, the idea behind
    how it got defined; needless to say that I think that was a bad idea.
    But that's what we've got! If they had dropped that requirement/idea
    the declaration syntax could have become "better" (more consistent,
    less cryptic, less convoluted, clearer). Now, after half a century,
    we just have to live with that, and folks who have "problems" with it
    should better not touch this language (or maybe not doing programming
    at all). The somewhat tragic aspect is that the "declaration follows
    use" idea was (IIRC) intended to _simplify_ the understanding of its
    concepts and use of the language; the consequences were seemingly not
    valued correctly.

    There are a number of things that I don't particularly like about C's
    declaration syntax, or where I think it would have been better if it
    were different.  But the "inside-to-outside" ordering is not one of
    them.  That is not because I think it is better or clearer than left-
    to- right ordering, but because when I compare to, say, Pascal, it's
    not a big issue for me.  Far bigger are :

    1. People put too much into a single type declaration, rather than
    building types out of logical parts with a purpose and a name.  They
    don't do it as much as Bart likes to pretend, but some people do it
    too much for my liking.  The language doesn't force you to do that -
    it's programmer style.  IMHO there is never a reason for a "pointer to
    an array of function pointers taking int and returning void" - no
    matter what syntax is used.

    Then you have a peculiar and restricted coding style.

    I don't believe so, no - at least, not compared to other code in my
    field. It /is/ restricted, but so is everyone's coding style.


    (Funny that when I suggest that nested loop breaks are uncommon,
    everyone says I'm wrong! Some even write 200-line made-up examples to
    prove their point.)

    I don't remember "everyone" saying you were wrong to say that nested
    loop breaks are uncommon - in fact, I don't remember /anyone/ saying
    that was wrong. A few people have suggested that they personally would
    often find some kind of multi-level break useful, but I do not believe
    many people think it is common, as a fraction of all C code they write.

    (You really should cut down on the paranoia and the exaggerations.)


    These are two actual function pointer arrays from my projects (not C):

        []ref proc hosthandlers = ...

        [pclnames.len]ref proc(pcl) px_handlertable

    There is no reason to abstract away that function pointer type.

    You probably do so in C /because/ the type involves * () and [] but have somehow persuaded yourself that it just better that way.

    Do you hear that whooshing noise? It is the sound of the point flying
    far above your head.

    Here is an example of some sensible function typedefs, all from
    third-party code (so not my "peculiar" style)

    struct tmrTimerControl;
    typedef struct tmrTimerControl * TimerHandle_t;
    typedef void (*TimerCallbackFunction_t)( TimerHandle_t xTimer );

    TimerHandle_t xTimerCreate( const char * const pcTimerName,
    TickType_t xTimerPeriodInTicks,
    UBaseType_t uxAutoReload,
    void * pvTimerID,
    TimerCallbackFunction_t pxCallbackFunction );

    typedef void (*TaskFunction_t)( void * );
    typedef BaseType_t (*TaskHookFunction_t)( void * );

    typedef void (*altcp_err_fn)(void *arg, err_t err);


    typedef void (*lwip_thread_fn)(void *arg);
    typedef void (*tcpip_init_done_fn)(void *arg);
    typedef void (*tcpip_callback_fn)(void *ctx);
    typedef void (* sys_timeout_handler)(void *arg);
    typedef void (*dns_found_callback)(const char *name,
    const ip_addr_t *ipaddr, void *callback_arg);

    Ask yourself why the typedefs are used. Look at the /names/. Those
    last four are all from the same network stack library, and are all
    typedefs for "void (*)(void*)". That function type could easily have
    been written out in full in each declaration that used them. Yet the
    actual functions using them specifically choose to use the type names
    that are relevant at the time.


    Do you really need me to spoon-feed you the reasons why this is all a
    good idea? People name types because it makes their code clearer, more robust, more flexible, more portable.


    Note that 'pcl' in my example /is/ a typedef; here it makes sense as it
    is used in 100s of places. This function pointer occurs in only one place.

    I'm sorry, I had mistaken you for a programmer who wanted to write good,
    clear programs. Naming things is not a shortcut to save keypresses.


    (The C version looks like: 'void (*name[N]))T)'. I used a tool and transcribed it, then I double-checked and found I'd written '(*name)[N]'
    not '(*name[N])'; I wouldn't have noticed.)

    BTW what name would be given to such a function pointer type? There is nothing obvious other than 'funcptr', but suppose there is more than one
    in scope?

    I have no idea what your code is supposed to do, so I have no idea what
    names would be good. Presumably you /do/ know what it is for - such as
    what "pcl" means - so /you/ pick good names. Maybe "host_handler_fn" ?


    Something else strikes me about breaking up a complex type-decl sequence into a chain of typedefs: if you take that list of typedefs, and rotate
    it 90 degrees c/w, you have something that resembles the LTR
    representation!


    If the details of the declaration syntax matter, you are doing it wrong.




    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@[email protected] to comp.lang.c on Tue Oct 20 10:25:41 2026
    From Newsgroup: comp.lang.c

    On 19/10/2026 23:27, Janis Papanagnou wrote:
    On 2026-10-19 21:35, Michael S wrote:
    On Mon, 19 Oct 2026 15:44:40 +0200
    Janis Papanagnou <[email protected]> wrote:

    On 2026-10-18 18:32, Michael S wrote:
    On Sun, 18 Oct 2026 18:11:18 +0200
    Janis Papanagnou <[email protected]> wrote:

    I don't recall to have used any language with infix-expressions
    that would have their monadic operators defined in postfix form.

    I am a Bear of Very Little Brain, and long words Bother Me.

    (If that quote is important for your argument, please explain.)


    Translation:
    1. I have no idea what unary * has to do with infix-expressions
    2. I don't appriciate use of the term "infix-expression" instead of more
    common (in context of description of C and similar languages) term
    'binary operators'.
    3. I don't know what "monadic operators defined in postfix form" means
    and have no plans to look for the meaning


    I'm sorry, these are (AFAICT) common terms, and I thought obvious.

    I am afraid your terminology is further from common use than you
    thought. ("Common use" of course depends on the context of the user -
    we are in the context of C programmers.) Your posts can be clearer if
    you use appropriate terminology.


    So let me explain and amend with more text and examples...

    Point 1. - I gave the hint that in languages that support RPN
    (= Reverse Polish Notation) things like monadic postfix operators
    (= having just _one_ argument applied _after_ the operator) are the
    natural way of writing expressions. Less so in languages, which are
    the majority since decades, that support expressions with infix
    operators (= the operator arguments left and right of the operator).


    RPN - Reverse Polish Notation - is certainly a well-known term, though
    the abbreviation might seem out of place. "Postfix" is the term most
    obvious in the context of C, as that is the term used in the standards.

    And while "x y +" is clearly RPN, "x *" is not - it could be part of an
    infix expression, or a unary postfix operator.

    "Monadic" /can/ refer to single argument functions or operators. But it
    can also mean something completely different - monadic operations are operations that work on "packaged" types that unpack the value, apply a function, and pack it in again. There is nothing of that kind in C (the language or standard library), but it is becoming a familiar term for
    users of C++ and is well-established in many other languages.

    The C standard using "unary" for single-argument operators.

    Similarly, "binary" is the normal term for two-argument operators, not "dyadic". (Though I don't think "dyadic" has any other common meanings.)


    Point 2. - A "binary operator" may be the '*' in the expressions
      a * b     typical infix notation (with parenthesis for precedence)
      a b *     RPN

    Normally known as "postfix", especially in C.

      * a b     PN (Polish Notation)

    There is no term "Polish Notation" - except as occasionally used to mean /postfix/ as a short form of "Reverse Polish Notation". RPN was
    invented, or at least popularised, by the Polish logician Jan
    Łukasiewicz (I admit to looking that up on Wikipedia!). There is no
    "PN" opposite.


    A "binary operator" is something different from an "infix expression"
    (the first one of the three; the others are RPN and PN examples).
    That's why I took the appropriate term to explain what I intended to
    explain.

    Yes, binary operators can be prefix, infix or postfix.


    Point 3. - "monadic" (see point 1). Applying to postfix form is best explained on another example; assume RPN
      a -       monadic (unary) minus (on one argument)

    Or, as the C world calls it, a postfix unary operator.

      a b -     dyadic (binary) minus (difference of two arguments)


    Or, as the C world calls it, a syntax error or a refugee from
    comp.lang.forth.

    Hope the terms are clear now. Now consider our original case, e.g.

      a * *b ...     multiply and dereference
      a - -b ...     subtract and negate

    as soon as we parse the second operator we know its kind. With postfix operators we'd have (assuming same semantics but with postfix operators)

      a * b * ...    now what is the second '*' at that point of parsing?
      a - b - ...    we don't expect that second '-' to be a negation.

    The compilers can handle every variant. For the users it's different;
    usually they seem to prefer unary operators to be prefixed (YMMV).

    The question (concerning "C") was; would it have been "better" (in any respect) if the dereferencing operator would have been defined in "C"
    as postfix operator (as you seem to prefer).

    Janis


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Tim Rentsch@[email protected] to comp.lang.c on Tue Oct 20 02:53:02 2026
    From Newsgroup: comp.lang.c

    [email protected] (Dan Cross) writes:

    In article <11b285v$121v2$[email protected]>,
    David Brown <[email protected]> wrote:

    On 17/10/2026 01:29, Janis Papanagnou wrote:

    On 2026-10-17 00:00, Keith Thompson wrote:

    Tim Rentsch <[email protected]> writes:

    Keith Thompson <[email protected]> writes:
    [...]

    There's a proposal for C2y to use goto labels as loop names, and a >>>>>> competing one to define a new syntax like "for NAME (;;)" :
    [...]

    I'm not particularly a fan of multi-level break/continue. But if
    we're going to have one of these, the second ("for NAME (;;)") is
    unquestionably better.

    Unquestionably? Why?

    Why would one question an opinion? ;-)

    Time didn't word it as a personal opinion - he made it clear that he
    doesn't think anyone else could have a different opinion.

    Tim often makes it sound as though he believes that his opinions
    are facts.

    I invite you to compare the statements made about David Parnas and
    his advice on software development, first those in the original
    edition of The Mythical Man-Month and second those in the revised
    (20th Anniversary) edition of MM-M, both of course by Fred Brooks.

    I learned a lot from Fred Brooks.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Tue Oct 20 12:41:55 2026
    From Newsgroup: comp.lang.c

    On 20/10/2026 09:01, David Brown wrote:
    On 19/10/2026 23:28, bart wrote:

    (Funny that when I suggest that nested loop breaks are uncommon,
    everyone says I'm wrong! Some even write 200-line made-up examples to
    prove their point.)

    I don't remember "everyone" saying you were wrong to say that nested
    loop breaks are uncommon - in fact, I don't remember /anyone/ saying
    that was wrong.

    (There was a LOT of antipathy towards my idea to fix the common case of 'loop-break' clashing with 'switch-break', BECAUSE it did not fix the
    problem of nested loop-break, which is uncommon, even though that wasn't
    the aim.)

    There is no reason to abstract away that function pointer type.

    You probably do so in C /because/ the type involves * () and [] but
    have somehow persuaded yourself that it just better that way.

    Do you hear that whooshing noise?  It is the sound of the point flying
    far above your head.

    Here is an example of some sensible function typedefs, all from third-
    party code (so not my "peculiar" style)


    typedef void (*TimerCallbackFunction_t)( TimerHandle_t xTimer );

    TimerHandle_t xTimerCreate(  const char * const pcTimerName,
                     TickType_t xTimerPeriodInTicks,
                     UBaseType_t uxAutoReload,
                     void * pvTimerID,
                     TimerCallbackFunction_t pxCallbackFunction );


    typedef void (*lwip_thread_fn)(void *arg);
    typedef void (*tcpip_init_done_fn)(void *arg);
    typedef void (*tcpip_callback_fn)(void *ctx);
    typedef void (* sys_timeout_handler)(void *arg);
    typedef void (*dns_found_callback)(const char *name,
                     const ip_addr_t *ipaddr, void *callback_arg);


    This is the kind of C I find hard to read. There are lots of typedefs
    but few uses of those typedefs that I can see, so I don't know how much difference they make.

    Except here:

    typedef void (*TimerCallbackFunction_t)( TimerHandle_t xTimer );

    TimerHandle_t xTimerCreate( const char * const pcTimerName,
    TickType_t xTimerPeriodInTicks,
    UBaseType_t uxAutoReload,
    void * pvTimerID,
    TimerCallbackFunction_t pxCallbackFunction );

    Without the typedef, I believe it would just be this:

    TimerHandle_t xTimerCreate( const char * const pcTimerName,
    TickType_t xTimerPeriodInTicks,
    UBaseType_t uxAutoReload,
    void * pvTimerID,
    void (*pxCallbackFunction)(TimerHandle_t));

    (I've left out the parameter name of the callback function, as I don't
    believe it is that useful.

    I've left in the regular parameter names, even though C doesn't need
    them, but they are quite heavy - you don't really need those
    Hungarian-style prefixes.)

    Well, I guess this buys you one thing: the parameter name for the last parameter is to the right of its type, rather than be inside it. But a C expert should not be fazed by that.

    Here is the same function as I might write it in an alternative syntax.

    I've kept the same names, but changed case-style and removed prefixes
    and suffixes. I've capitalised user-type names:

    func TimerCreate( # (retain case if FFI import)
    ichar timername,
    Ticktype timerperiodinticks,
    Ubasetype autoreload,
    ref void timerid,
    ref proc(Timerhandle) callbackfn)

    In this form, it's hard to see what benefit a typedef would give for
    that last parameter; it is simple enough.


    Ask yourself why the typedefs are used.  Look at the /names/.  Those
    last four are all from the same network stack library, and are all
    typedefs for "void (*)(void*)".

    Until you mentioned it, I hadn't noticed. So typedef has done a good job
    of hiding that useful fact! But looking more closely, it is the first
    four of the last five.

    Let's take one:

    typedef void (*lwip_thread_fn)(void *arg);

    That 'arg' is not much use for a start (other than being a hint that
    this particular (...) is where the parameters go).

    So, maybe this is used like this:

    void F(lwip_thread_fn lwip_thread_callback);

    Here you have two identifiers imparting the sort kind of information; a tautology.

    If that function pointer pattern is common, or recurs in a suite of
    functions, I might also have used a typedef, but with a common name.
    Then only one would be needed, say:

    typedef void (*stack_callbackfn)(void);

    I might have done the same in that alternate syntax as it would start to
    get cluttery: 'ref proc(ref void)', but also in order to define that
    common pattern in one place.

    Note that 'pcl' in my example /is/ a typedef; here it makes sense as
    it is used in 100s of places. This function pointer occurs in only one
    place.

    I'm sorry, I had mistaken you for a programmer who wanted to write good, clear programs.  Naming things is not a shortcut to save keypresses.

    Isn't that one of the main uses of typedefs? So as to give a handy, 'euphonious' one-token alias to an elaborate typedef.

    It also allows you to change the type in one place without having to
    update hundreds of instances.

    It also allows the type to be opaque.

    Saving keypresses is bonus benefit, but if it is shorter, then it can
    also help readability as other critical elements are not overshadowed.

    So I'm not sure what objection you have to this particular use of it.

    Here is the one place I do remember using typedef for a function pointer
    (from an old project, not in C):

    type fnptr = ref proc

    repeat
    (fnptr(pcptr^))^()
    until stopped

    It's used as a cast, but reason I have it is because with simple cast
    syntax, which is 'T(X)', the meaning without it would be ambiguous (a
    grammar issue that I might fix one day).

    Rather than fallback to standard cast syntax (which is 'cast(X, T)'),
    this was tidier.

    BTW what name would be given to such a function pointer type?

    I have no idea what your code is supposed to do,

    It's a table of function pointers! All sharing the same signature.

    That's pretty generic. Is it really that hard to guess? You don't need
    to know what they do, other than at some point they will be called as handlertable[i](arg).


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@[email protected] (Dan Cross) to comp.lang.c on Tue Oct 20 12:22:50 2026
    From Newsgroup: comp.lang.c

    In article <[email protected]>,
    Tim Rentsch <[email protected]> wrote:
    [email protected] (Dan Cross) writes:
    [snip]
    Tim often makes it sound as though he believes that his opinions
    are facts.

    I invite you to compare the statements made about David Parnas and
    his advice on software development, first those in the original
    edition of The Mythical Man-Month and second those in the revised
    (20th Anniversary) edition of MM-M, both of course by Fred Brooks.

    I suppose that you must think that this is some sort of profound
    statement, and that by assigning this kind of pedagogical
    exercise that you expect me to learn something relevant. But I
    find this sophomoric imperative grotesquely arrogant.

    Like Keith, I don't need you to give me homework assignments. I
    have some suspicion about what you are referring to from Brooks,
    but I am not going to waste my time chasing down what you can't
    be bothered to just say.

    If you mean to say something, then say it, or do not. In either
    case, do not presume to waste my or anyone else's time with poor
    attempts at the socratic method. "I invite you...", indeed.

    I learned a lot from Fred Brooks.

    That's nice. So did I.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@[email protected] to comp.lang.c on Tue Oct 20 14:58:05 2026
    From Newsgroup: comp.lang.c

    On 20/10/2026 13:41, bart wrote:
    On 20/10/2026 09:01, David Brown wrote:
    On 19/10/2026 23:28, bart wrote:

    (Funny that when I suggest that nested loop breaks are uncommon,
    everyone says I'm wrong! Some even write 200-line made-up examples to
    prove their point.)

    I don't remember "everyone" saying you were wrong to say that nested
    loop breaks are uncommon - in fact, I don't remember /anyone/ saying
    that was wrong.

    (There was a LOT of antipathy towards my idea to fix the common case of 'loop-break' clashing with 'switch-break', BECAUSE it did not fix the problem of nested loop-break, which is uncommon, even though that wasn't
    the aim.)

    It is correct that the idea of having a "loop-break" statement was
    considered and quickly rejected by people looking at multi-level breaks.
    It would be silly, when first making a language change to handle one
    type of coding situation, to pick a special case when a more general
    solution could be used. I don't think anyone was arguing that the
    desire for breaking out of nested loops was /common/, but I don't think
    many people felt breaking out of a switch in a loop was common either.
    Both needs are relatively rare in general C coding.

    But while the consensus is that a "loop-break" statement is not worth
    adding to C, that is a completely different thing than claiming that "everyone" said you were wrong to say nested loop breaks are common!

    So - again - please cut the paranoia and exaggerations, and /read/ what
    people write, rather than the conspiracies you imagine they write.


    There is no reason to abstract away that function pointer type.

    You probably do so in C /because/ the type involves * () and [] but
    have somehow persuaded yourself that it just better that way.

    Do you hear that whooshing noise?  It is the sound of the point flying
    far above your head.

    Here is an example of some sensible function typedefs, all from third-
    party code (so not my "peculiar" style)


    typedef void (*TimerCallbackFunction_t)( TimerHandle_t xTimer );

    TimerHandle_t xTimerCreate(  const char * const pcTimerName,
                      TickType_t xTimerPeriodInTicks,
                      UBaseType_t uxAutoReload,
                      void * pvTimerID,
                      TimerCallbackFunction_t pxCallbackFunction );


    typedef void (*lwip_thread_fn)(void *arg);
    typedef void (*tcpip_init_done_fn)(void *arg);
    typedef void (*tcpip_callback_fn)(void *ctx);
    typedef void (* sys_timeout_handler)(void *arg);
    typedef void (*dns_found_callback)(const char *name,
                      const ip_addr_t *ipaddr, void *callback_arg);


    This is the kind of C I find hard to read. There are lots of typedefs
    but few uses of those typedefs that I can see, so I don't know how much difference they make.

    Yes, sorry, I should have posted tens of thousands of lines of C code
    using these. I'm sure that would have made things much clearer than a
    couple of extracted examples.


    But let us take a concrete example. These network functions are from
    the LWIP network stack, which is designed to be used on small embedded
    systems that may not have any kind of OS - so it uses call-backs for asynchronous programming.

    An example API function is this :

    err_t dns_gethostbyname(const char *hostname, ip_addr_t *addr,
    dns_found_callback found, void *callback_arg)

    The returned "err_t" can be "ERR_OK" (indicating the "hostname" is in
    the DNS cache and *addr is set to the IP), "ERR_ARG" for argument
    errors, or "ERR_INPROGRESS" to indicate that the stack is looking up the
    DNS name, and will call the callback when there is a final result or
    timeout.


    Without typedef's, that function signature would be something like :

    signed char dns_gethostbyname(const char *hostname, struct ip_addr
    *addr, void (*found)(const char *name, const struct ip_addr
    *ipaddr, void *callback_arg), void *callback_arg);


    Do you expect anyone to believe you if you claim this is easier to read
    than the real declaration using typedefs? I'll believe you if you say
    you find the original hard to read - but not if you claim the
    "untypedef'ed" version is clearer.

    The typedefs let you understand the code piece by piece.

    A "dns_found_callback" is a callback function called when a dns lookup
    has finished - that's clear from its name. It is called with arguments
    the name that was looked up, the ip address that was found, and a user-supplied extra argument that can be used as you want. That's
    simple and clear.

    The "dns_gethostbyname" function is a function to find a host's IP
    address, given its name - that's clear from the name. It is called with
    the name to look up, a pointer to a place to store the resulting IP
    address, a callback function of type "dns_found_callback" if it can't
    answer immediately, and a user-supplied extra argument for the callback function. This is again, simple and clear.



    Except here:

     typedef void (*TimerCallbackFunction_t)( TimerHandle_t xTimer );

     TimerHandle_t xTimerCreate(  const char * const pcTimerName,
                       TickType_t xTimerPeriodInTicks,
                       UBaseType_t uxAutoReload,
                       void * pvTimerID,
                       TimerCallbackFunction_t pxCallbackFunction );

    Without the typedef, I believe it would just be this:

    TimerHandle_t xTimerCreate(  const char * const pcTimerName,
                     TickType_t xTimerPeriodInTicks,
                     UBaseType_t uxAutoReload,
                     void * pvTimerID,
                     void (*pxCallbackFunction)(TimerHandle_t));

    (I've left out the parameter name of the callback function, as I don't believe it is that useful.

    I've left in the regular parameter names, even though C doesn't need
    them, but they are quite heavy - you don't really need those Hungarian- style prefixes.)

    /C/ does not need the parameter names - /programmers/ need them, because
    they tell you want they do. Omitting them is as smart as calling all
    your functions "foo1", "foo2", etc., just because C does not require
    sensible names.

    The point of using typedefs here is that they make the xTimerCreate()
    function declaration simpler and clearer, and it tells the programmer
    what is going on. It tells the programmer that the parameter is a TimerCallbackFunction - not just any old function that takes a
    TimerHandle_t parameter. The programmer knows that a suitable argument
    is their "flash_the_green_led" function, but not their
    "initialise_timer" function that happens coincidentally to have the same signature.


    Well, I guess this buys you one thing: the parameter name for the last parameter is to the right of its type, rather than be inside it. But a C expert should not be fazed by that.

    Here is the same function as I might write it in an alternative syntax.

    I've kept the same names, but changed case-style and removed prefixes
    and suffixes. I've capitalised user-type names:

    func TimerCreate(                 # (retain case if FFI import)
        ichar     timername,
        Ticktype  timerperiodinticks,
        Ubasetype autoreload,
        ref void  timerid,
        ref proc(Timerhandle) callbackfn)

    In this form, it's hard to see what benefit a typedef would give for
    that last parameter; it is simple enough.

    I am glad I don't have to work with your code - whatever language you
    use. The number one skill for programmers is picking good names, and
    you flumped that one.



    Ask yourself why the typedefs are used.  Look at the /names/.  Those
    last four are all from the same network stack library, and are all
    typedefs for "void (*)(void*)".

    Until you mentioned it, I hadn't noticed. So typedef has done a good job
    of hiding that useful fact! But looking more closely, it is the first
    four of the last five.

    It is not "hiding a useful fact" - it is abstracting away from an
    unintended coincidence. My own preference is to use stronger types,
    precisely so that things could not be mixed up. I'd have :

    typedef struct { void * arg; } lwip_thread_arg;
    typedef void (*lwip_thread_fn)(lwip_thread_arg * arg);

    typedef struct { void * arg; } tcpip_init_done_arg;
    typedef void (*tcpip_init_done_fn)(tcpip_init_done_arg * arg);

    (If I were to go back in time and change things in C, I'd make "typedef" define new types, not type aliases.)


    Let's take one:

     typedef void (*lwip_thread_fn)(void *arg);

    That 'arg' is not much use for a start (other than being a hint that
    this particular (...) is where the parameters go).

    So, maybe this is used like this:

      void F(lwip_thread_fn lwip_thread_callback);

    Here you have two identifiers imparting the sort kind of information; a tautology.

    You don't need to duplicate the name when it is not helpful - and you certainly should not do so when it is clearly wrong (a thread function
    is not a callback function, even if the signatures match). A real
    function signature using this type is :

    sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread,
    void *arg, int stacksize, int prio);


    If that function pointer pattern is common, or recurs in a suite of functions, I might also have used a typedef, but with a common name.
    Then only one would be needed, say:

     typedef void (*stack_callbackfn)(void);

    /You/ might have written that, but it would be significantly worse code.
    You are obsessed with the details of the syntax of the type, instead
    of looking at what it represents and what it will mean in the code.

    There can be occasional uses for "generic" names, like :

    typedef void (*fp_void)(void);

    just as there are uses for generic "int" types rather than types like "size_t", "int32_t", "TickType_t", etc. But using well-named types
    conveys vital information. Using badly named types, or re-using named
    types inappropriately, makes code worse.


    I might have done the same in that alternate syntax as it would start to
    get cluttery: 'ref proc(ref void)', but also in order to define that
    common pattern in one place.

    Note that 'pcl' in my example /is/ a typedef; here it makes sense as
    it is used in 100s of places. This function pointer occurs in only
    one place.

    I'm sorry, I had mistaken you for a programmer who wanted to write
    good, clear programs.  Naming things is not a shortcut to save
    keypresses.

    Isn't that one of the main uses of typedefs? So as to give a handy, 'euphonious' one-token alias to an elaborate typedef.

    No, it should not be your main use of typedef - but it might
    occasionally be a reason.


    It also allows you to change the type in one place without having to
    update hundreds of instances.

    It also allows the type to be opaque.

    Now you are beginning to understand! Yes, these are two key reasons for typedefs.


    Saving keypresses is bonus benefit, but if it is shorter, then it can
    also help readability as other critical elements are not overshadowed.

    I agree - but that is a bonus, not an aim in itself. There is a balance
    to be found between being too verbose, and not being explicit enough.
    The "right" balance point depends very much on the context, the code,
    and the target audience.


    So I'm not sure what objection you have to this particular use of it.

    I don't object to having shorter aliases when appropriate. I object to
    it as a prime motivation.


    Here is the one place I do remember using typedef for a function pointer (from an old project, not in C):

        type fnptr = ref proc

        repeat
            (fnptr(pcptr^))^()
        until stopped

    It's used as a cast, but reason I have it is because with simple cast syntax, which is 'T(X)', the meaning without it would be ambiguous (a grammar issue that I might fix one day).

    Rather than fallback to standard cast syntax (which is 'cast(X, T)'),
    this was tidier.

    BTW what name would be given to such a function pointer type?

    I have no idea what your code is supposed to do,

    It's a table of function pointers! All sharing the same signature.

    I can't see any use in a table of function pointers. I can see a use in
    a table of event handlers, a table of timer callback functions, a table
    of state machine state handlers, etc.

    It's like saying you have an array of "int". No, you have an array of
    the days in each month of the year, or an array of timestamps of
    keypresses, or an array of the cost of different coffee mugs.


    That's pretty generic. Is it really that hard to guess? You don't need
    to know what they do, other than at some point they will be called as handlertable[i](arg).


    That is why I guessed "host_handler_fn" as a name, but you snipped that.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Tue Oct 20 15:11:35 2026
    From Newsgroup: comp.lang.c

    On 20/10/2026 02:03, Waldek Hebisch wrote:
    bart <[email protected]> wrote:

    OK. But they HAD to create C? There were quite a few languages in the
    early 70s too: like Pascal, Fortran, PL/I, Coral-66, plus of course BCPL
    and B. So why a new one?

    You ignore fact that Ritche wanted reasonably fast code from
    very simple compiler.

    According to DC's quote from HOPL, it was also more fun to create a new language.


    PL/I had most needed features. But PL/I was a big language,
    to run on small machine they would have to take tiny subset
    and then add extentions. Basicaly they would end up with a
    language which is very far from PL/I.

    There were PL/360 and PL/M, although those were more specific, more 'machine-oriented' languages. (I implemented one for PDP10 but it was a
    port of a systems language from a GEC machine.)

    Anyway, a more general subset could have been used.


    Similarly, BCPL was too complicated, B and C were simplifications
    and adaptations small machine.

    I think that Pascal was too late: nominally it was created earlier
    but I think that it was available to Bell Labs only after they
    did initial work leading to C. And Pascal shared problem of
    speed on small machines. Note that later UCSD Pascal which
    run on micros compiled to interpreted bytecode, which significantly
    reduced performance.

    It would not have been hard to use Pascal as a starting point for a
    workable systems language. Wirth wouldn't have approved, but his
    languages were too pure, too academic; some of us had things we needed
    to get done!

    Here I mean adapting Pascal for a competing systems language.

    In my hands some aspects would be simplified (eg. no nested functions,
    no closures), thus making it easier to generate decent code with a
    simple compiler.



    FORTRAN syntax looked nothing like C! Unless you mean the general
    pattern of 'INTEGER A, B' which was shared by half of all languages.

    I think more pattern of

    INTEGER A(20), B

    which has similar structure to C variable declarations.

    OK. That was typical for the time. But in Fortran it didn't get much
    more complicated than that. Maybe 2D arrays and so on.

    Of course,
    FORTRAN had no pointers (and structures or unions), so Ritche had
    to invent syntax for them.

    There were three languages from that era that I know had pointers or references, and which allowed composing arbitrary types with arrays and pointers, two of which were Algol68 and Pascal.

    Both used a 100% LTR form.

    The other was C. There, several choices were made:

    * To start with that Fortran style except that [] are used

    * To decree that that 'A[20]' syntax is supposed to match indexing of
    A as it might appear in an expression

    * To introduce "*" as a prefix dereference operator in expressions ...

    * ... which then means that a prefix "*" appears in the declaration too

    * A further complication was to allow function pointers within that a
    declaration list

    * Yet one more which came later was to add 'const', where placement now
    gets confusing

    But to stay with pointers, take this expression:

    *A[i]

    C precedence rules mean this is parsed as *(A[i]), which means that a
    type written as 'T *A[N]' must be an array of pointers to T (I had to
    think for a few seconds!).

    But suppose you wanted a pointer to array of T? The expression for that
    would be:

    (*A)[i]

    And so the declaration has to be 'T (*A)[N]' too.

    So it is unfortunate that parentheses used to control precedence in an expression now also have to appear in type declarations (where they are
    often next to () used for parameter lists, for further confusion).

    ==============================================

    So, what would have happened with a postfix deref op? (Ignore whether
    '*' would still be a good choice.) My first example would be this:

    A*[i]

    Here, it would mean that A is dereferenced, then indexed; A must then be
    a pointer to an array of T.

    But suppose we wanted the original array of pointers to T, where you
    index first then dereference. That is written like this:

    A[i]*

    You simply swap the order of [] and *.

    So, PARENTHESES HAVE BEEN ELIMINATED for purpose of disambiguating array/pointer and pointer/array, both within expressions and within type-declarations.

    How about that? Further, most of the type-spec is now LTR; only the
    base-type has to stay on the left. Access terms in expressions will be
    fully LTR.

    IMO C suffers because typedef was added late in the game and
    function prototypes are much later. Prototypes need types and
    to get it one needs "hole" in variable declaration. Where the
    hole should be is specified by the C syntax, but placement of
    hole is probably least clear aspect of declarations.

    I thought that 'hole' was where 'int A[10]' mean one thing in normal declaration but another within a parameter list.

    IMO C declaration syntax was a mistake, but as real life shows
    it was not a fatal mistake, people can adapt.

    A mistake that could so easily have been avoid by choosing a different precedence as shown above. Did none of the thousand people working at
    Bell Labs (according to a comment in DC's follow-ip) spot this and say anything?

    Had no-one even glanced at a Pascal spec, if there was no working copy?
    It would have transformed C type syntax.

    (ACTUALLY IT IS NOT TOO LATE. A secondary postfix deref op could have
    been added. This could have been done 50 years ago, with the original eventually deprecated.

    But this is a common theme of mine whether I perceive a problem that
    people grudgingly admit might not be idea. But nothing was ever done to
    fix it even after decades.)


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@[email protected] to comp.lang.c on Tue Oct 20 16:56:31 2026
    From Newsgroup: comp.lang.c

    On 2026-10-20 10:25, David Brown wrote:
    On 19/10/2026 23:27, Janis Papanagnou wrote:
    On 2026-10-19 21:35, Michael S wrote:
    [...]

    I'm sorry, these are (AFAICT) common terms, and I thought obvious.

    I am afraid your terminology is further from common use than you
    thought.

    I'm afraid you are wrong here; in several ways. I'll expand below.

    ("Common use" of course depends on the context of the user -
    we are in the context of C programmers.)  Your posts can be clearer if
    you use appropriate terminology.


    So let me explain and amend with more text and examples...

    Point 1. - I gave the hint that in languages that support RPN
    (= Reverse Polish Notation) things like monadic postfix operators
    (= having just _one_ argument applied _after_ the operator) are the
    natural way of writing expressions. Less so in languages, which are
    the majority since decades, that support expressions with infix
    operators (= the operator arguments left and right of the operator).


    RPN - Reverse Polish Notation - is certainly a well-known term, though
    the abbreviation might seem out of place.

    I don't know why you think it would be "out of place". Since I gave
    an explanation that made use of that concept I named it, and since
    Michael had expressed difficulties with some of my (what I thought
    to be commonly known, even here) terms I presented "RPN" with its
    explicit meaning as you see above. (It's IMO good style to "explain"
    acronyms when first used; but sadly - especially also here! - we
    rarely see that, so I find it strange that you mention that at all.)

    "Postfix" is the term most
    obvious in the context of C, as that is the term used in the standards.

    It's not about being obvious in context of C, it's about accuracy
    of the used term in the context of my conceptual explanations.
    (If I'd intended to explain something concerning the C-definition I
    probably might have used the C-standard term. But I was explaining
    something principle and used standard and common CS terminology.)


    And while "x y +" is clearly RPN, "x *" is not - it could be part of an infix expression, or a unary postfix operator.

    Sure. If you reinspect my post you'll see that I used that term in
    context of "x y +" and not in context of "a * b * ..." that I used
    later. So your comment here is just unnecessary noise and void.


    "Monadic" /can/ refer to single argument functions or operators.

    In CS I learned that "monadic" very specifically has the meaning I
    used it for. - /Britannica/ (for example) [also] explains:
    "Monadic and dyadic operators refer to the number of arguments
    or operands an operator takes"

    As an intermediate _general_ note; please accept that I use common
    CS terms if I'm speaking about programming languages in general and
    about design concepts. - I know and acknowledge that such terms are
    often redefined (for specific contexts) or regularly misused. Don't
    expect me to deliberately blur my language to express something for
    an audience that *might* not have knowledge beyond "C". (I'd think
    most of the audience here knows the CS terminology, though. If not
    then I'll be glad to explain.)

    But it
    can also mean something completely different - monadic operations are operations that work on "packaged" types that unpack the value, apply a function, and pack it in again.  There is nothing of that kind in C (the language or standard library), but it is becoming a familiar term for
    users of C++ and is well-established in many other languages.

    (I know "many other languages" but don't recall to have seen mentioned
    that word in another language with a meaning other than explained. So
    I cannot know that it was given another meaning in some other special
    area (like "packed types"). But I'd also expect that IT people at least
    know the common CS terms.)


    The C standard using "unary" for single-argument operators.

    Similarly, "binary" is the normal term for two-argument operators, not "dyadic".  (Though I don't think "dyadic" has any other common meanings.)

    If we compare in discussions monadic and dyadic operators it would be
    more a terminology issue with "unary" since the counterpart would then
    be "binary", and "binary" is a homonymous word in that area and also on
    that explanation level. - I prefer a most fitting choice of words.

    And I'm sorry if some cannot follow my post because of that. But I'm
    willing to explain if some terms are not known to some here; just ask.


    Point 2. - A "binary operator" may be the '*' in the expressions
       a * b     typical infix notation (with parenthesis for precedence) >>    a b *     RPN

    Normally known as "postfix", especially in C.

    "Normally" I've seen that notation called RPN sometimes also as postfix notation. (Please don't try to teach a duck swimming. And I suggest to
    not join the club of folks who generalize based on opinions with words
    like "normally".)


       * a b     PN (Polish Notation)

    There is no term "Polish Notation" -

    My academic education as well as some [well reputed] online resources
    disagree with you. (I wonder why you didn't check your _opinion_ here!)

    except as occasionally used to
    mean /postfix/ as a short form of "Reverse Polish Notation".  RPN was invented, or at least popularised, by the Polish logician Jan
    Łukasiewicz (I admit to looking that up on Wikipedia!).  There is no
    "PN" opposite.

    Oh, so you have just missed it! - Retry... https://en.wikipedia.org/wiki/Polish_notation

    And next time better stay quiet instead of trying to play the smartass
    without need! (It's really not necessary to post as much as you do.)



    A "binary operator" is something different from an "infix expression"
    (the first one of the three; the others are RPN and PN examples).
    That's why I took the appropriate term to explain what I intended to
    explain.

    Yes, binary operators can be prefix, infix or postfix.

    You don't need to confirm that. (It's common knowledge.)

    [ snip rest ]

    (I've got tired and bored about your post.) :-/

    But thanks for making it obvious that I cannot expect common and long
    existing CS terms to be generally understood here.

    I admit, that I might have made a wrong assumption about CS knowledge
    here; before your post I thought it were just one or two individuals.
    (Now my guess would be that it could be three or four individuals.)

    Janis

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@[email protected] to comp.lang.c on Tue Oct 20 17:02:37 2026
    From Newsgroup: comp.lang.c

    On 20/10/2026 16:11, bart wrote:

    The other was C. There, several choices were made:

    * To start with that Fortran style except that [] are used

    * To decree that that 'A[20]' syntax is supposed to match indexing of
      A as it might appear in an expression

    * To introduce "*" as a prefix dereference operator in expressions ...

    * ... which then means that a prefix "*" appears in the declaration too

    * A further complication was to allow function pointers within that a
      declaration list

    I don't see a problem with that. If you need to declare a function
    pointer, you need to declare it in a declaration list.

    To me, the big disadvantage of C's declaration syntax is that it lets
    you declare things of different (but related) types in the same
    declaration. I don't have a problem with :

    int (*my_func_pointer)(int);
    int my_array[20];

    but I /do/ have a problem with :

    int (*my_func_pointer)(int), my_array[20];

    or, more common and therefore worse :

    int * a, b;

    The way to deal with this is, of course, simply not writing such mixed declarations. But some people /do/ - living with other peoples' code is
    the bane of all programmers.

    I am confident that there could have been a nicer syntax, and function
    pointer (or function type) syntax is particularly ugly. But it works
    well enough in practice that I cannot see it as a problem or even inconvenience.


    * Yet one more which came later was to add 'const', where placement now
      gets confusing

    Some people do find it hard to understand the difference between :

    const int * p;
    int * const q;
    const int * const r;

    I note that this is despite the clear left-to-right nature of "const" here.

    Many newbie mistakes with const will be caught by the compiler, and once
    you get used to it, you should be fine.


    But to stay with pointers, take this expression:

       *A[i]

    C precedence rules mean this is parsed as *(A[i]), which means that a
    type written as 'T *A[N]' must be an array of pointers to T (I had to
    think for a few seconds!).

    If you instead forget that you can declare more than one thing in one declaration, you can write :

    T* A[i];

    Then it is quite clear.


    But suppose you wanted a pointer to array of T? The expression for that would be:

        (*A)[i]

    And so the declaration has to be 'T (*A)[N]' too.


    Yes. Declaration syntax follows usage. (If you don't like the operator precedence, or the fact that dereferencing is pre-fix in C, unlike, say, Pascal, then that's an orthogonal dislike.)


    So it is unfortunate that parentheses used to control precedence in an expression now also have to appear in type declarations (where they are often next to () used for parameter lists, for further confusion).

    You know how to use typedefs to make code clearer.

    Complicated types are a minority. Most object declarations are either
    things, arrays of things, or pointers to things - not combinations of
    these. And most function declarations are just function declarations,
    not arrays of function pointers or other complex types.


    ==============================================

    So, what would have happened with a postfix deref op? (Ignore whether
    '*' would still be a good choice.) My first example would be this:

       A*[i]

    Here, it would mean that A is dereferenced, then indexed; A must then be
    a pointer to an array of T.

    But suppose we wanted the original array of pointers to T, where you
    index first then dereference. That is written like this:

       A[i]*

    You simply swap the order of [] and *.

    So, PARENTHESES HAVE BEEN ELIMINATED for purpose of disambiguating array/pointer and pointer/array, both within expressions and within type-declarations.

    Agreed.

    But does that make a significant difference? I don't think so. I'd
    have to see a lot more real-life examples to get a feeling for whether
    postfix dereference would be better or worse than prefix - saving the occasional parentheses is not sufficient.


    How about that? Further, most of the type-spec is now LTR; only the base-type has to stay on the left. Access terms in expressions will be
    fully LTR.

    IMO C suffers because typedef was added late in the game and
    function prototypes are much later.  Prototypes need types and
    to get it one needs "hole" in variable declaration.  Where the
    hole should be is specified by the C syntax, but placement of
    hole is probably least clear aspect of declarations.

    I thought that 'hole' was where 'int A[10]' mean one thing in normal declaration but another within a parameter list.

    That's a different thing entirely. (And while I don't find it confusing
    that array and pointer parameters mean the same thing in C, I do see it
    as a wasted opportunity for better static checking and optimisation of
    code.)


    IMO C declaration syntax was a mistake, but as real life shows
    it was not a fatal mistake, people can adapt.

    A mistake that could so easily have been avoid by choosing a different precedence as shown above. Did none of the thousand people working at
    Bell Labs (according to a comment in DC's follow-ip) spot this and say anything?

    I suspect the folks at Bell Labs were too busy writing real code to be bothered by how confused you would be with artificially complex types.

    Life is full of little decisions that, with hindsight, might have been sub-optimal choices but are nonetheless good enough in practice. C's declaration syntax is one of those decisions. It's worth learning from
    that and picking a clearer syntax for new languages, but it is not worth obsessing over its use in existing languages.



    Had no-one even glanced at a Pascal spec, if there was no working copy?
    It would have transformed C type syntax.

    (ACTUALLY IT IS NOT TOO LATE. A secondary postfix deref op could have
    been added. This could have been done 50 years ago, with the original eventually deprecated.

    It /is/ too late - far, far too late. It would be a terrible idea to
    add a new postfix dereference operator to give two different operators
    with no benefit other than very occasionally reducing the need for parentheses. If "*p" really bothers you, write "p[0]" instead (in expressions, not type declarations).


    But this is a common theme of mine whether I perceive a problem that
    people grudgingly admit might not be idea. But nothing was ever done to
    fix it even after decades.)


    What is the common theme? You pick something that lots of people
    consider as "it's maybe uglier than it need be, but it works fine in
    practice" and pretend that you alone discovered the issue? Then you go completely haywire about how terrible and unbelievable it is, call the C designers idiots and claim to be a genius because your irrelevant
    language does something different? Then comes the paranoia, and claims
    that no one will "admit there is a problem", and the absurd insistence
    that we all "do something about it". Eventually the thread dies away,
    until you bring up the same shit half a year later. For years, and
    years, and years. Is that the common theme you are talking about?


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@[email protected] to comp.lang.c on Tue Oct 20 17:32:39 2026
    From Newsgroup: comp.lang.c

    On 20/10/2026 16:56, Janis Papanagnou wrote:
    On 2026-10-20 10:25, David Brown wrote:
    On 19/10/2026 23:27, Janis Papanagnou wrote:
    On 2026-10-19 21:35, Michael S wrote:
    [...]

    I'm sorry, these are (AFAICT) common terms, and I thought obvious.

    I am afraid your terminology is further from common use than you thought.

    I'm afraid you are wrong here; in several ways. I'll expand below.

    You don't need to be defensive here - I am trying to help you see /why/
    your terms might not have been the best choices. It is not criticism of
    your post, just advice on your terminology so that it does not detract
    from understanding the content.

    (It is already clear that they were not good choices - Michael has long experience in software development of many types, and if they were not
    obvious to him in the context of your posts, they were not good terms to
    use.)

    You post a lot of interesting things. You made a post with unnecessary convoluted terminology that distracted from the content of your post,
    perhaps based on the particular usage of particular terms in the
    particular computer science courses you took.

    So my apologies for trying to be helpful!

    (And do look up "monads" and "monadic operations" - they are all the
    rage in many programming languages these days.)

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@[email protected] (Dan Cross) to comp.lang.c on Tue Oct 20 19:24:33 2026
    From Newsgroup: comp.lang.c

    In article <11b7k22$2v8e5$[email protected]>, bart <[email protected]> wrote:
    On 20/10/2026 09:01, David Brown wrote:
    On 19/10/2026 23:28, bart wrote:

    (Funny that when I suggest that nested loop breaks are uncommon,
    everyone says I'm wrong! Some even write 200-line made-up examples to
    prove their point.)

    I don't remember "everyone" saying you were wrong to say that nested
    loop breaks are uncommon - in fact, I don't remember /anyone/ saying
    that was wrong.

    (There was a LOT of antipathy towards my idea to fix the common case of >'loop-break' clashing with 'switch-break', BECAUSE it did not fix the >problem of nested loop-break, which is uncommon, even though that wasn't
    the aim.)

    Those are two different things. No one disagrees with you that
    "nested break from a switch inside of a loop" is relatively more
    common than other variants.

    Using that as an excuse not to provide a more general mechanism
    because you already have a proposal for the specific case is
    what I and others took you to task for. I find this ironic,
    since you rail against things in C that you do not like, citing
    the most ridiculous examples you can think of that do not show
    up in actual programs, yet for something where it is pointed out
    to you that your solution does not generalize, you claim that it
    does not need to because ... the general case rarely shows up in
    a real program.

    There is no reason to abstract away that function pointer type.

    You probably do so in C /because/ the type involves * () and [] but
    have somehow persuaded yourself that it just better that way.

    Do you hear that whooshing noise?  It is the sound of the point flying
    far above your head.

    Here is an example of some sensible function typedefs, all from third-
    party code (so not my "peculiar" style)

    typedef void (*TimerCallbackFunction_t)( TimerHandle_t xTimer );

    TimerHandle_t xTimerCreate(  const char * const pcTimerName,
                     TickType_t xTimerPeriodInTicks,
                     UBaseType_t uxAutoReload,
                     void * pvTimerID,
                     TimerCallbackFunction_t pxCallbackFunction );

    typedef void (*lwip_thread_fn)(void *arg);
    typedef void (*tcpip_init_done_fn)(void *arg);
    typedef void (*tcpip_callback_fn)(void *ctx);
    typedef void (* sys_timeout_handler)(void *arg);
    typedef void (*dns_found_callback)(const char *name,
                     const ip_addr_t *ipaddr, void *callback_arg);

    This is the kind of C I find hard to read. There are lots of typedefs
    but few uses of those typedefs that I can see, so I don't know how much >difference they make.

    You again missed the entire point. You may not see many uses
    of them, but as David says, the `typedef`s give you
    domain-specific *names* understandable to the programmer: a
    programmer can see the `sys_timeout_handler` type instantly know
    that this has a different function than the,
    `tcpip_callback_fn`, despite the having the same type.

    The other point is that the ridiculous examples you make up to
    illustrate your distaste for C declaration syntax basically do
    not appear in real programs.

    [snip]
    I've left in the regular parameter names, even though C doesn't need
    them, but they are quite heavy - you don't really need those
    Hungarian-style prefixes.)

    Well, I guess this buys you one thing: the parameter name for the last >parameter is to the right of its type, rather than be inside it. But a C >expert should not be fazed by that.

    Here is the same function as I might write it in an alternative syntax.

    I've kept the same names, but changed case-style and removed prefixes
    and suffixes. I've capitalised user-type names:

    func TimerCreate( # (retain case if FFI import)
    ichar timername,
    Ticktype timerperiodinticks,
    Ubasetype autoreload,
    ref void timerid,
    ref proc(Timerhandle) callbackfn)

    In this form, it's hard to see what benefit a typedef would give for
    that last parameter; it is simple enough.

    What is your point? Do you have one? If you don't want to use
    C, don't use C.

    There are plenty of languages that can do this kind of thing
    that are not C and have syntax and semantics closer to what you
    seem to want. Here's an example in Rust:

    pub trait TimerHandle { ... }

    fn CreateTimer<T>(
    timer_name: &str,
    period: std::time::Duration,
    auto_reload: bool,
    timer_id: T,
    handler: fn(&dyn TimerHandle),
    ) -> Result<Timer<T>, TimerError>

    I didn't know what an `UBaseType_t` is, and while "autoreload"
    sounded pretty intuitive, I wasn't sure about the semantics, so
    I looked it up (the example comes from `FreeRTOS`). In this
    context, it is a boolean saying whether the timer should repeat
    with the given periodicity, or whether it is a one-shot.

    The timer_id is opaque to the timer, and it looks like it's used
    to facilitating the handler accessing timer-specific data. In
    C, passing it as a `void *` is used as a way to get a poor-man's
    overloading. But Rust has generics, I just made it generic over
    some type T.

    If I were writing this from scratch in Rust, a language that has
    generics, closures, and so sum types, I'd do the whole thing
    differently; see the end for an example.

    But I digress. The point here is, Bart, that alternatives exist
    if you don't like C. You don't have to keep posting, over and
    over again, in comp.lang.c of all places, about how oh so
    terribly awful C is. If you don't want to program in C, simply
    don't program in C.

    Ask yourself why the typedefs are used.  Look at the /names/.  Those
    last four are all from the same network stack library, and are all
    typedefs for "void (*)(void*)".

    Until you mentioned it, I hadn't noticed. So typedef has done a good job
    of hiding that useful fact! But looking more closely, it is the first
    four of the last five.

    Let's take one:

    typedef void (*lwip_thread_fn)(void *arg);

    That 'arg' is not much use for a start (other than being a hint that
    this particular (...) is where the parameters go).

    So, maybe this is used like this:

    void F(lwip_thread_fn lwip_thread_callback);

    I have no idea what you're trying to say here. The obvious (and
    honestly, excusable) syntax error aside, what is F? It's a
    function that, what, takes two function pointers?

    The type defined by `lwip_thread_fn` is a pointer to a function
    that takes a void pointer (`void *`) as its sole arugment, and
    returns `void` (that is, has no meaningful return value).

    Intuitively, the name implies that this is the function run as
    some thread, so we'd pass it to a thread creation function. The
    usual shape of those things is to give them a pointer to some
    function to run in the new thread, and a pointer to some
    arguments to be passed to that function. For example:

    void
    whatever(void *argp)
    {
    struct Args *args = argp;
    while (keep_running()) {
    // Do the thing the thread is supposed to do.
    }
    thread_exit(SUCCESS);
    }

    thread_t *
    start_the_whatever_thread(void)
    {
    struct Args *args = malloc(sizeof(*args));
    if (args == NULL) abort();
    memset(args, 0, sizeof(*args));
    args->whatever = something();
    // etc...
    thread_t *thr = thread_create(whatever, args);
    if (thr == NULL) abort();
    return thr;
    }

    Something could start this as:

    thread_t *whatever_id = start_the_whatever_thread();

    At some point later, if you want to wait for the thread to
    exit, you'd run:

    (void)thread_join(whatever_id);

    Note this is decently complex behavior, but it's actually quite
    intuitive from the name and the type.

    Here you have two identifiers imparting the sort kind of information; a >tautology.

    That's not what a tautology is.

    If that function pointer pattern is common, or recurs in a suite of >functions, I might also have used a typedef, but with a common name.

    Then you loose the domain specificity; you can't tell from the
    name whether you need an LwIP thread, or a callback, or a
    something run in a different thread, or just a plain 'ol
    function you want to apply to run every now and again for a side
    effect.

    Then only one would be needed, say:

    typedef void (*stack_callbackfn)(void);

    I might have done the same in that alternate syntax as it would start to
    get cluttery: 'ref proc(ref void)', but also in order to define that
    common pattern in one place.

    I dunno. Sounds like you have no idea what the code that David
    posted is meant to do. But that's a "you" problem.

    Note that 'pcl' in my example /is/ a typedef; here it makes sense as
    it is used in 100s of places. This function pointer occurs in only one
    place.

    I'm sorry, I had mistaken you for a programmer who wanted to write good,
    clear programs.  Naming things is not a shortcut to save keypresses.

    Isn't that one of the main uses of typedefs? So as to give a handy, >'euphonious' one-token alias to an elaborate typedef.

    It also allows you to change the type in one place without having to
    update hundreds of instances.

    It also allows the type to be opaque.

    The point is that the name you chose is meaningless to anyone
    other than you. What's a PCL? Phase Control Line? Printer
    Command Language? Photon Compressor Loop?

    Saving keypresses is bonus benefit, but if it is shorter, then it can
    also help readability as other critical elements are not overshadowed.

    So I'm not sure what objection you have to this particular use of it.

    Have you ever written a large program that was maintained by
    anyone other than yourself?

    Here is the one place I do remember using typedef for a function pointer >(from an old project, not in C):

    type fnptr = ref proc

    repeat
    (fnptr(pcptr^))^()
    until stopped

    It's used as a cast, but reason I have it is because with simple cast >syntax, which is 'T(X)', the meaning without it would be ambiguous (a >grammar issue that I might fix one day).

    Rather than fallback to standard cast syntax (which is 'cast(X, T)'),
    this was tidier.

    I can only guess at what this may mean. Hazarding a guess,
    `pcptr` is a "pointer to a program counter", which is a
    reference type to some type that represents some executable
    memory location in the program. You then have a loop that runs
    until "stopped" is true where you indirect the program counter
    pointer, cast it to a pointer to a function, and then invoke
    the function, right? One presumes you have the, "PC Pointer"
    because it changes over time, otherwise, you'd just give
    whatever it points to a name and call it.

    More generally, I fail to see what this is trying to
    demonstrate. If it's to show some sort of imagined superiority
    over C, I don't see it; that's sort of thing is easy enough to
    write:

    typedef void (*fnptr)(void);

    // Assume uintptr_t *pcptr is declared somewhere.
    do {
    ((fnptr)*pcptr)();
    } while (!stopped);

    E.g.,

    ```
    term% cat b.c
    #include <stdbool.h>
    #include <stddef.h>
    #include <stdint.h>
    #include <stdio.h>

    static void first(void);

    typedef void (*fnptr)(void);
    bool stopped = false;
    uintptr_t pc = (uintptr_t)first;
    uintptr_t *pcptr = &pc;

    void
    done(void)
    {
    printf("done\n");
    stopped = true;
    }

    void
    second(void)
    {
    printf("second\n");
    *pcptr = (uintptr_t)done;
    }

    void
    first(void)
    {
    printf("first\n");
    *pcptr = (uintptr_t)second;
    }

    void
    run(void)
    {
    do {
    ((fnptr)*pcptr)();
    } while (!stopped);
    }

    int
    main(void)
    {
    run();
    return 0;
    }
    term% gcc-16 -std=c11 -pedantic -o b b.c
    term% ./b
    first
    second
    done
    term%
    ```

    BTW what name would be given to such a function pointer type?

    I have no idea what your code is supposed to do,

    It's a table of function pointers! All sharing the same signature.

    That's pretty generic. Is it really that hard to guess? You don't need
    to know what they do, other than at some point they will be called as >handlertable[i](arg).

    That part is fine.

    What's utterly mystifying is what you are trying to show, if
    anything, by posting it. Is this supposed to prove some kind of
    point? Your code is not _a priori_ easier to understand than
    the equivalent C code; if anything, it is harder to understand
    because of your poorly chosen names.

    - Dan C.

    Rust implementation of Timers, mentioned above<--

    As mentioned above, if I were providing the FreeRTOS timers API
    in an alternative language, I'd write it differently from the
    start. In particular, I'd use an enumeration to describe the
    behavior with respect to repeating, and I'd use a closure to
    obviate the need for the opaque id. Something that isn't easy
    to express in the original API is a type of repeating timer that
    waits for the initial period, and then repeats with some
    different period.

    Something like this:

    ```rust
    pub mod timer {
    use std::sync::atomic::{AtomicBool, Ordering};
    use std::time::Duration;

    /// Errors that may occur when working with timers.
    #[derive(Clone, Copy, Debug)]
    pub enum Error {
    Running,
    CantStop,
    WontStop,
    }

    /// Describes the kind of a timer, as defined by its
    /// periodicity.
    ///
    /// A timer can either be a `OneShot` timer, which fires
    /// once, after its timeout expires, or it may be a Repeating
    /// timer, which will automatically reset after its handler
    /// is run and continue firing at the rate defined by the
    /// initial timeout, or it can be a periodic timer, that
    /// will fire the first time at the initial timeout, and
    /// then repeatedly a potentially different timeout. This
    /// use case can be simulated by a OneShot timer that
    /// creates a repeating Timer, but
    ///
    /// Once started, Repeating and Periodic timers continue
    /// firing until explicitly stopped.
    #[derive(Clone, Copy, Debug)]
    pub enum Kind {
    OneShot,
    Repeating,
    Periodic(Duration),
    }

    /// A named timer, that is handled by the given callback.
    pub struct Timer<'a, F> {
    pub name: &'a str,
    pub kind: Kind,
    pub timeout: Duration,
    callback: F,
    running: AtomicBool,
    // Whatever other innards...
    // ...
    }

    /// A read-only "view" into the timer.
    pub trait TimerView {
    fn name(&self) -> &str;
    fn kind(&self) -> Kind;
    fn timeout(&self) -> Duration;
    }

    impl<'a, F: Fn(&dyn TimerView)> Timer<'a, F> {
    /// Creates a new named timer of the given kind with an
    /// initial timeout. When the timeout expires, it will
    /// automatically invoke the given handler.
    pub fn new(
    name: &'a str,
    timeout: Duration,
    kind: Kind,
    callback: F,
    ) -> Timer<'a, F> {
    let running = AtomicBool::new(false);
    Self {
    name,
    kind,
    callback,
    timeout,
    running,
    }
    }

    /// Starts the timer.
    pub fn start(&self) -> Result<(), Error> {
    if self.running.swap(true, Ordering::AcqRel) {
    return Err(Error::Running);
    }
    self.arm(self.timeout)?;
    Ok(())
    }

    /// Stops the timer.
    ///
    /// Note that this inherently races with the timer firing,
    /// and a timer event that occurs while we are disabling
    /// the timer may still invoke `fired` after this returns.
    ///
    /// Callers are advised to determine definitively that
    /// there are no events pending for this timer before
    /// destroying the `Timer` object.
    pub fn stop(&self) -> Result<(), Error> {
    let was_running = self.running.swap(false, Ordering::AcqRel);
    if !was_running {
    return Err(Error::WontStop);
    }
    self.disarm();
    Ok(())
    }

    // Automatically called when the timeout fires.
    //
    // # Safety
    //
    // Nothing may be mutably borrowing a reference to the
    // Timer object when this is called.
    pub(super) unsafe fn fired(&self) -> Result<(), Error> {
    if !self.running.load(Ordering::Acquire) {
    return Ok(());
    }
    (self.callback)(self);
    match self.kind {
    Kind::OneShot => Ok(()),
    Kind::Repeating => self.arm(self.timeout),
    Kind::Periodic(period) => self.arm(period),
    }
    }

    // Arranges for `self.fired(self)` to be called when
    // the given timeout expires.
    fn arm(&self, timeout: Duration) -> Result<(), Error> {
    // Does whatever one does here to actually arm the
    // timer (e.g., calls a HAL to actually program a
    // physical timer to interrupt after the amount of
    // time specified by `Duration`, for example).
    // ...
    Ok(())
    }

    // Disables an armed timer, so that it does not fire
    // after this returns.
    fn disarm(&self) -> Result<(), Error> {
    // whatever one does here to disarm an active timer
    // ...
    Ok(())
    }
    }

    impl<F> TimerView for Timer<'_, F> {
    fn name(&self) -> &str { self.name }
    fn kind(&self) -> Kind { self.kind }
    fn timeout(&self) -> Duration { self.timeout }
    }
    }
    ```

    One might use this with something like,

    ```
    let value = 42;
    let cb = move |timer: &dyn timer::TimerView| {
    println!(
    "Timer '{}' fired; value is {} and duration was {} ms",
    timer.name(),
    value,
    timer.timeout().as_millis()
    );
    };
    let timeout = std::time::Duration::from_millis(100);
    let timer = timer::Timer::new("timer", timeout, timer::Kind::OneShot, &cb);
    timer.start().expect("Timer started");
    //... at some point the timer fires and prints,
    // 'Timer 'timer1' fired; value is 42 and duration was 100 ms'
    }
    ```
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Tue Oct 20 21:07:20 2026
    From Newsgroup: comp.lang.c

    On 20/10/2026 16:02, David Brown wrote:
    On 20/10/2026 16:11, bart wrote:

    The other was C. There, several choices were made:

    * To start with that Fortran style except that [] are used

    * To decree that that 'A[20]' syntax is supposed to match indexing of
       A as it might appear in an expression

    * To introduce "*" as a prefix dereference operator in expressions ...

    * ... which then means that a prefix "*" appears in the declaration too

    * A further complication was to allow function pointers within that a
       declaration list

    I don't see a problem with that.  If you need to declare a function pointer, you need to declare it in a declaration list.

    To me, the big disadvantage of C's declaration syntax is that it lets
    you declare things of different (but related) types in the same
    declaration.

    Yes, but that doesn't bite so much because it is uncommon.

    or, more common and therefore worse :

        int * a, b;

    (See below.)

    * Yet one more which came later was to add 'const', where placement now
       gets confusing

    Some people do find it hard to understand the difference between :

        const int * p;
        int * const q;
        const int * const r;

    I note that this is despite the clear left-to-right nature of "const" here.
    I was going to say it was right-to-left, but it can be considered both
    and thus not clear:

    const int const * const p;
    1 2 3

    const 1 applies to the basetype to its right.
    const 2 applies to the basetype to its left.

    (Both also can be in the middle with compound types like 'long long'!)

    const 3 is tricky: I think it applies to the * to its left, since it
    says that the pointer value itself is const. But 'p' has type 'pointer
    to', so it could apply to that directly.

    What about this however:

    int * const * p;

    1 2 3

    I think here, const 2 applies to * 1, which is to it's left, and can't
    apply to 'p' as that is the other side of the * 3.

    Fair to say that is a complete mess, and it is error prone.

    With a LTR syntax that a postfix deref would achieve, 'const' would
    always be written immediately to the left of any * modifiers. (It is meaningless for arrays and functions.)

    It is never applied directly to a variable name.

    For base types, it can be applied on the left, but C would still allow
    it on the right or in the middle, or all three with duplicates.

    That means there would be an ambiguity here where there is no identifier between 'int' and 'const':

    (const int const *)

    For such reasons I would restrict base type const to be only on the left.)
    Complicated types are a minority.

    I've showed even simple types or trying to use 'const' get becomes
    confusing.

    So, PARENTHESES HAVE BEEN ELIMINATED for purpose of disambiguating
    array/pointer and pointer/array, both within expressions and within
    type-declarations.

    Agreed.

    But does that make a significant difference?  I don't think so.

    It would make a HUGE difference:

    (1) It helps to fix that confusion above

    (2) You don't need parentheses so no need to remember if you want
    (*A)[] or *A[]. Those will disappear from expressions too; less
    clutter all round.

    (3) It simplifies indexing of pointer-to-array from (*A)[i] to A*[i], so
    that actual array pointers, which are more type-safe, could start to
    appear more in C rather than the current T* idiom

    (4) For pointers to structs, these are the patterns:

    prefix * With -> With postfix *

    (*P).m P->m P*.m
    (**P).m (*P)->m P**.m
    (***P).m (**P)->m P***.m

    Which column looks the tidiest?

    (5) With prefix *, a pointer type looks like 'T*'; notice the * is on
    the right, not left! With postfix *, it would all be consistent. You
    also wouldn't have 'T*A'; that would be an error (T* only happens
    when there is no name)

    (6) Your 'int * a, b' example would become:

    int a *, b;

    Much easier, even with that space, to see that '*' does not belong to
    the base type but is a modifier for that variable.

    It doesn't fix everything, so you'd still have this:

    int p* = &a;
    p* = a;

    To fix this requires that all modifiers apply to the base type. But this
    would be a massive change. The above is merely what happens when *
    becomes postfix.

    A mistake that could so easily have been avoid by choosing a different
    precedence as shown above. Did none of the thousand people working at
    Bell Labs (according to a comment in DC's follow-ip) spot this and say
    anything?

    I suspect the folks at Bell Labs were too busy writing real code to be bothered by how confused you would be with artificially complex types.

    So you agree the process was very different compared to that which lead
    to Ada for example? Just a couple of guys left to do their own thing.

    (Maybe they were respected enough that no one dared to offer any
    constructive criticism, or if they did then it was dismissed. As happens here.)


    (ACTUALLY IT IS NOT TOO LATE. A secondary postfix deref op could have
    been added. This could have been done 50 years ago, with the original
    eventually deprecated.

    It /is/ too late - far, far too late.  It would be a terrible idea to
    add a new postfix dereference operator to give two different operators
    with no benefit other than very occasionally reducing the need for parentheses.

    But a special operator P->m to do the same job as (*P).m was fine! The
    new op would eliminate the need for ->.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Tue Oct 20 21:30:32 2026
    From Newsgroup: comp.lang.c

    On 20/10/2026 20:24, Dan Cross wrote:
    In article <11b7k22$2v8e5$[email protected]>, bart <[email protected]> wrote:

    The point is that the name you chose is meaningless to anyone
    other than you. What's a PCL? Phase Control Line? Printer
    Command Language? Photon Compressor Loop?

    Within the context of that application then it would be clear. You're
    just being overly hostile.

    (Within the app, PCL is the name of a bytecode language, and 'pcl' is a reference to a specific instruction.

    Next time I'll just use T for such examples, since the type is not
    relevant to the point. Although that didn't stop you seizing upon my F function.)


    Here is the one place I do remember using typedef for a function pointer
    (from an old project, not in C):

    type fnptr = ref proc

    repeat
    (fnptr(pcptr^))^()
    until stopped

    More generally, I fail to see what this is trying to
    demonstrate.

    Not much. It is just a rare example of my using aliases for function
    pointers. Because I suggested such aliases are often unnecessary and
    partly used in C to get around the fiddly type syntax that would arise.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Michael S@[email protected] to comp.lang.c on Tue Oct 20 23:33:37 2026
    From Newsgroup: comp.lang.c

    On Tue, 20 Oct 2026 15:11:35 +0100
    bart <[email protected]> wrote:

    On 20/10/2026 02:03, Waldek Hebisch wrote:
    bart <[email protected]> wrote:

    OK. But they HAD to create C? There were quite a few languages in
    the early 70s too: like Pascal, Fortran, PL/I, Coral-66, plus of
    course BCPL and B. So why a new one?

    You ignore fact that Ritche wanted reasonably fast code from
    very simple compiler.

    According to DC's quote from HOPL, it was also more fun to create a
    new language.


    PL/I had most needed features. But PL/I was a big language,
    to run on small machine they would have to take tiny subset
    and then add extentions. Basicaly they would end up with a
    language which is very far from PL/I.

    There were PL/360 and PL/M, although those were more specific, more 'machine-oriented' languages. (I implemented one for PDP10 but it was
    a port of a systems language from a GEC machine.)


    PL/M is approximately contemporary to C, most likely Ritchie had first
    compiler working few months before Kildall. But input language of the
    early C compilers was likely further away from what it evolved later
    than early PL/M to later its variant.
    C was self-hosted on minicomputer from the beginning.
    PL/M originally required more powerful and expensive host. Eventually
    PL/M host requirements were reduced below those of C, but it took couple
    of years.

    Anyway, a more general subset could have been used.


    I suppose that you wholeheartedly agree. I don't. I never found computer language design fun.


    Similarly, BCPL was too complicated, B and C were simplifications
    and adaptations small machine.

    I think that Pascal was too late: nominally it was created earlier
    but I think that it was available to Bell Labs only after they
    did initial work leading to C. And Pascal shared problem of
    speed on small machines. Note that later UCSD Pascal which
    run on micros compiled to interpreted bytecode, which significantly
    reduced performance.

    It would not have been hard to use Pascal as a starting point for a
    workable systems language. Wirth wouldn't have approved, but his
    languages were too pure, too academic; some of us had things we
    needed to get done!

    Here I mean adapting Pascal for a competing systems language.


    Pascal without several extensions does not seem suitable for system programming.

    In my hands some aspects would be simplified (eg. no nested
    functions, no closures), thus making it easier to generate decent
    code with a simple compiler.


    But then, it's not Pascal. And still needs extensions.



    FORTRAN syntax looked nothing like C! Unless you mean the general
    pattern of 'INTEGER A, B' which was shared by half of all
    languages.

    I think more pattern of

    INTEGER A(20), B

    which has similar structure to C variable declarations.

    OK. That was typical for the time. But in Fortran it didn't get much
    more complicated than that. Maybe 2D arrays and so on.

    Of course,
    FORTRAN had no pointers (and structures or unions), so Ritche had
    to invent syntax for them.

    There were three languages from that era that I know had pointers or references, and which allowed composing arbitrary types with arrays
    and pointers, two of which were Algol68 and Pascal.

    Both used a 100% LTR form.

    The other was C. There, several choices were made:

    * To start with that Fortran style except that [] are used

    * To decree that that 'A[20]' syntax is supposed to match indexing of
    A as it might appear in an expression

    * To introduce "*" as a prefix dereference operator in expressions ...

    * ... which then means that a prefix "*" appears in the declaration
    too

    * A further complication was to allow function pointers within that a
    declaration list

    * Yet one more which came later was to add 'const', where placement
    now gets confusing

    But to stay with pointers, take this expression:

    *A[i]

    C precedence rules mean this is parsed as *(A[i]), which means that a
    type written as 'T *A[N]' must be an array of pointers to T (I had to
    think for a few seconds!).

    But suppose you wanted a pointer to array of T? The expression for
    that would be:

    (*A)[i]

    And so the declaration has to be 'T (*A)[N]' too.

    So it is unfortunate that parentheses used to control precedence in
    an expression now also have to appear in type declarations (where
    they are often next to () used for parameter lists, for further
    confusion).

    ==============================================

    So, what would have happened with a postfix deref op? (Ignore whether
    '*' would still be a good choice.) My first example would be this:

    A*[i]

    Here, it would mean that A is dereferenced, then indexed; A must then
    be a pointer to an array of T.

    But suppose we wanted the original array of pointers to T, where you
    index first then dereference. That is written like this:

    A[i]*

    You simply swap the order of [] and *.

    So, PARENTHESES HAVE BEEN ELIMINATED for purpose of disambiguating array/pointer and pointer/array, both within expressions and within type-declarations.

    How about that? Further, most of the type-spec is now LTR; only the base-type has to stay on the left. Access terms in expressions will
    be fully LTR.

    IMO C suffers because typedef was added late in the game and
    function prototypes are much later. Prototypes need types and
    to get it one needs "hole" in variable declaration. Where the
    hole should be is specified by the C syntax, but placement of
    hole is probably least clear aspect of declarations.

    I thought that 'hole' was where 'int A[10]' mean one thing in normal declaration but another within a parameter list.

    IMO C declaration syntax was a mistake, but as real life shows
    it was not a fatal mistake, people can adapt.

    A mistake that could so easily have been avoid by choosing a
    different precedence as shown above. Did none of the thousand people
    working at Bell Labs (according to a comment in DC's follow-ip) spot
    this and say anything?


    Methinks there were less than 100 people exposed to C before it became
    too late. May be, just 50.

    Had no-one even glanced at a Pascal spec, if there was no working
    copy? It would have transformed C type syntax.

    (ACTUALLY IT IS NOT TOO LATE. A secondary postfix deref op could have
    been added. This could have been done 50 years ago, with the original eventually deprecated.

    But this is a common theme of mine whether I perceive a problem that
    people grudgingly admit might not be idea. But nothing was ever done
    to fix it even after decades.)


    It was. There are many new languages.
    Today, C sees little use outside of small to mid-sized mocrocontrollers
    and OS kernels.
    Most user-layer applications on general purpose computers are written
    in newer languages.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@[email protected] (Dan Cross) to comp.lang.c on Tue Oct 20 21:44:36 2026
    From Newsgroup: comp.lang.c

    In article <11b8j17$3btus$[email protected]>, bart <[email protected]> wrote:
    On 20/10/2026 20:24, Dan Cross wrote:
    In article <11b7k22$2v8e5$[email protected]>, bart <[email protected]> wrote:

    The point is that the name you chose is meaningless to anyone
    other than you. What's a PCL? Phase Control Line? Printer
    Command Language? Photon Compressor Loop?

    Within the context of that application then it would be clear. You're
    just being overly hostile.

    Not really. You are, I presume, posting that code to try and
    make some kind of point about how "readable" it is. But it's
    not readable unless you already know what it does.

    On the other hand, the code David posted _is_ readable, because
    it uses the language to encode domain-specific information into
    type names.

    (Within the app, PCL is the name of a bytecode language, and 'pcl' is a >reference to a specific instruction.

    Next time I'll just use T for such examples, since the type is not
    relevant to the point. Although that didn't stop you seizing upon my F >function.)

    You just don't get it. I suspect you have no idea what the
    `typedef`s David posted actually represent.

    Here is the one place I do remember using typedef for a function pointer >>> (from an old project, not in C):

    type fnptr = ref proc

    repeat
    (fnptr(pcptr^))^()
    until stopped

    More generally, I fail to see what this is trying to
    demonstrate.

    Not much. It is just a rare example of my using aliases for function >pointers. Because I suggested such aliases are often unnecessary and
    partly used in C to get around the fiddly type syntax that would arise.

    Yeah, you really just don't get it.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Tue Oct 20 23:43:29 2026
    From Newsgroup: comp.lang.c

    On 20/10/2026 22:44, Dan Cross wrote:
    In article <11b8j17$3btus$[email protected]>, bart <[email protected]> wrote:
    On 20/10/2026 20:24, Dan Cross wrote:
    In article <11b7k22$2v8e5$[email protected]>, bart <[email protected]> wrote:

    The point is that the name you chose is meaningless to anyone
    other than you. What's a PCL? Phase Control Line? Printer
    Command Language? Photon Compressor Loop?

    Within the context of that application then it would be clear. You're
    just being overly hostile.

    Not really. You are, I presume, posting that code to try and
    make some kind of point about how "readable" it is. But it's
    not readable unless you already know what it does.

    What it does not relevant. This is simply defining an array of T. But
    because T happens to be a function pointer, DB insists that an alias
    must be created, and a new name invented.

    Why? Probably because in C, the syntax for function pointers gets hairy.

    On the other hand, the code David posted _is_ readable, because
    it uses the language to encode domain-specific information into
    type names.

    Maybe we should create aliases for function signatures more often then,
    then we can encode that extra info.

    So that instead of, for example:

    void SomeFunc(int x, int y) {printf("%d %d\n", x, y);}

    you do:

    typedef void Take2Ints(int x, int y);

    Take2Ints SomeFunc {printf("%d %d\n", x, y);}

    If you have a suite of functions sharing the signature, then it might be
    a good idea. But funnily enough, you never see this being done.

    (I don't know if this is legal C; but it works fine with my compiler:

    c:\m>type fred.c
    #include <stdio.h>

    typedef void Take2Ints(int x, int y);

    Take2Ints SomeFunc{printf("%d %d\n", x, y);}

    int main(void) { SomeFunc(10, 20); }

    c:\m>bcc -r -q fred
    10 20

    )

    Yeah, you really just don't get it.
    One of us doesn't get it.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Wed Oct 21 00:01:05 2026
    From Newsgroup: comp.lang.c

    On 20/10/2026 21:33, Michael S wrote:
    On Tue, 20 Oct 2026 15:11:35 +0100
    bart <[email protected]> wrote:

    I suppose that you wholeheartedly agree. I don't. I never found computer language design fun.

    The fun part is afterwards when you use your very own language. Quite a
    way to get there though.

    Methinks there were less than 100 people exposed to C before it became
    too late. May be, just 50.

    Were you there? You seem confident of those figures! I've no idea what
    went on, myself; I can only speculate.


    Had no-one even glanced at a Pascal spec, if there was no working
    copy? It would have transformed C type syntax.

    (ACTUALLY IT IS NOT TOO LATE. A secondary postfix deref op could have
    been added. This could have been done 50 years ago, with the original
    eventually deprecated.

    But this is a common theme of mine whether I perceive a problem that
    people grudgingly admit might not be idea. But nothing was ever done
    to fix it even after decades.)


    It was. There are many new languages.
    Today, C sees little use outside of small to mid-sized mocrocontrollers
    and OS kernels.
    Most user-layer applications on general purpose computers are written
    in newer languages.


    I still see C everywhere, for example in the APIs of libraries like SDL,
    STB, GTK, OpenGL, Raylib, GMP, plus the APIs for many Windows
    subsystems, plus Linux.

    It's also popular as a target language for compilers (when LLVM is too
    much). Amateur compiler writers also seem to love creating C or C subset compilers more than any other language (they perceive it as simpler than
    it really is).

    And many language projects are still written in C, or at bootstrapped
    with C.

    This is all desktop machines still. Of course many are also migrating to products like Rust, Go and Zig.

    For me, the fact that there's still an appetite for a language of this
    class is one reason I still persist with mine.



    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Tim Rentsch@[email protected] to comp.lang.c on Tue Oct 20 16:10:48 2026
    From Newsgroup: comp.lang.c

    [email protected] (Waldek Hebisch) writes:

    Tim Rentsch <[email protected]> wrote:

    [email protected] (Waldek Hebisch) writes:

    Lawrence D?Oliveiro <[email protected]d> wrote:

    On Tue, 13 Oct 2026 07:23:40 -0000 (UTC), Waldek Hebisch wrote:

    So what those counts indicate: majority of loops is simple, that is >>>>> have no early exit. Vast majority of early exits is done via
    'return'.

    My experience in my own C code is quite the opposite. Lots of loops
    have exits in the middle, leading me to use forms like ?for (;;)?. I
    also try to avoid putting ?return? anywhere other than the end of a
    function, to make it easier to see the flow of control.

    Well, usually there is a lot of loops. Those with exit in the
    middle are still significant.

    Concernig 'return', having it in place where all work inside function
    is done help me to see flow control and avoids complications. In
    case of search functions it means return from the middle of the loop.
    IMO possible alternatives like flag variables or break and retrun
    after loop are worse.

    I rarely use 'break' to exit a loop. Part of this is that I try to
    write standard loops so that they complete as part of the loop test
    (i.e., in while() or for() control expressions). That isn't the
    whole story though so let me talk about 'return'.

    I counted various constructs in a small suite of 2 programs (1306
    lines in 3 files). There are 4 breaks outside switches and 32
    loops in total. My gut feeling is that this proportion is
    reasonable close to typical in my code. For comparison, there
    are 67 functions and 70 'if'-s.

    Probably that is close to what I see for my own code, if we
    count 'return' out of a loop.

    Most of the functions I write have exactly one return, at the end of
    the function. I estimate this pattern accounts for around 85% of
    all functions, let's say plus or minus 5%.

    In code above about half of functions is 'void' and there are 34
    explicit returns (of which at least 2 are early returns).

    I almost never use void functions. I'm used to a functional style,
    and it's natural to return something in almost all cases.

    Sometimes functions have early returns for errors or exceptional
    conditions.

    Code above contains 16 occurences of 'exit(1)'. One of those is
    in a macro that is used 10 times, so actually there are 25 places
    which call 'exit(1)'. That is related to the programs being
    simple utilities, there is no attempt to error recovery, on error
    programs simply print error message and exit.

    okay. I don't use exit() often but I have no problem with that.

    Early returns are easily seen to lie outside the main
    body of function processing so they don't interfere with
    understanding what the rest of the function is doing or how it
    works.

    A fairly common sub-pattern are functions most of whose body is a
    switch() statement, with all of the switch() cases being a simple
    return.

    Code above has 2 switches, both are in parsing functions, where
    cases either move to next state or signal error. Parsing functions
    also open file and close it when finished and return data structure
    with parsed info.

    In other kinds of code I might use switch() more often. Maybe I
    can try putting together a small application where switch() is more
    likely and see what I get.

    It does sometimes happen that a function will have a loop with a
    return in the middle, and also a return at the end for what to do if
    the loop terminates. To me having an in-loop return looks better
    than using an assignment and a break.

    A fairly rare but important pattern is what I might call vectoring
    or decomposition. Here the function body serves to distinguish and
    separate out different regimes of subprocessing. To continue
    processing in a particular regime, a return is used not to directly
    yield a value but rather to call a further function to handle that
    sub-domain. The benefit here is both to keep function bodies small
    and to allow re-use of commonly called sub-functions.

    Two aspects are important for having these different styles work
    together. One is that it's easy to distinguish the different kinds
    of patterns, and by far the most simple pattern is the most common.
    The other is to be sure to keep function bodies small. Keeping
    function bodies small goes a long way in making them easy to
    understand, which obviously is a key property in writing good code.
    Also keeping function bodies small effectively prevents mixing
    different styles in a single function, serving to reinforce point
    one.

    I think that in general my C code has similar characteristics.

    Yes it sounds that way.

    But
    let me note that while I have a lot of small functions, I also have
    some which are bigger. I suspect that 10% or more of my code is
    in functions that are bigger then 30 lines. Such functions
    frequently have several variables and there is setup stage to
    initialize things, actual processing and final part (cleanups,
    possibly extraction of result). Stages are clearly sepatated
    by their position inside function, OTOH are strongly coupled due
    to use of variables. My feeling here is that in case of strongly
    coupled code with no reusable parts keeping it inside single
    function is more managable than trying to split it into smaller
    functions.

    It's natural for me not to let functions get too large, which means
    more than about 60 lines of code. But beyond that wanting to write
    small functions doesn't mean only tiny functions. My "10% or more"
    function size may be a little smaller than yours, but not much
    smaller. Also I observe empirically an interesting property, which
    is that if we multiply the number of functions of size N by N, the
    result is roughly constant across the range of function sizes. So
    for example if there are three functions whose bodies have 50 lines
    then there are roughly 50 functions whose bodies have three lines.
    And that holds approximately across the whole range of function
    sizes (with a standard deviation about half the average). So there
    are lots of little functions but also functions of sizes in the
    20s, 30s, 40s and 50s. Does that sound similar to your own code?
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@[email protected] to comp.lang.c on Tue Oct 20 17:05:49 2026
    From Newsgroup: comp.lang.c

    David Brown <[email protected]> writes:
    [...]
    Without typedef's, that function signature would be something like :

    signed char dns_gethostbyname(const char *hostname, struct ip_addr
    *addr, void (*found)(const char *name, const struct ip_addr
    *ipaddr, void *callback_arg), void *callback_arg);

    I might write that as:

    signed char dns_gethostbyname(
    const char *hostname,
    struct ip_addr *addr,
    void (*found)(
    const char *name,
    const struct ip_addr *ipaddr,
    void *callback_arg
    ),
    void *callback_arg
    );

    so the indentation and structure reflects the semantics. I find
    that much clearer than your version. (I'm not commenting on the
    merits of typedefs.)
    --
    Keith Thompson (The_Other_Keith) [email protected]
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@[email protected] (Dan Cross) to comp.lang.c on Wed Oct 21 00:56:01 2026
    From Newsgroup: comp.lang.c

    In article <11b8qqg$3ejlp$[email protected]>, bart <[email protected]> wrote:
    On 20/10/2026 22:44, Dan Cross wrote:
    In article <11b8j17$3btus$[email protected]>, bart <[email protected]> wrote:
    On 20/10/2026 20:24, Dan Cross wrote:
    In article <11b7k22$2v8e5$[email protected]>, bart <[email protected]> wrote: >>>
    The point is that the name you chose is meaningless to anyone
    other than you. What's a PCL? Phase Control Line? Printer
    Command Language? Photon Compressor Loop?

    Within the context of that application then it would be clear. You're
    just being overly hostile.

    Not really. You are, I presume, posting that code to try and
    make some kind of point about how "readable" it is. But it's
    not readable unless you already know what it does.

    What it does not relevant. This is simply defining an array of T. But >because T happens to be a function pointer, DB insists that an alias
    must be created, and a new name invented.

    Why? Probably because in C, the syntax for function pointers gets hairy.

    I dunno; your syntax didn't seem any clearer to me.

    On the other hand, the code David posted _is_ readable, because
    it uses the language to encode domain-specific information into
    type names.

    Maybe we should create aliases for function signatures more often then,
    then we can encode that extra info.

    So that instead of, for example:

    void SomeFunc(int x, int y) {printf("%d %d\n", x, y);}

    you do:

    typedef void Take2Ints(int x, int y);

    Take2Ints SomeFunc {printf("%d %d\n", x, y);}

    If you have a suite of functions sharing the signature, then it might be
    a good idea. But funnily enough, you never see this being done.

    Yeah, you really don't get it.

    You remind me of the guy at Google who objected to importing the
    `std::` namespace in C++ into the default scope; "oh, so what;
    we should all write ::std::whatever::foo<::std::blah>(...)?!" as
    if finding the most stupidly extreme example was somehow a
    useful technical argument. He also spent all his time on
    mailing lists arguing about how everybody else Got It Wrong. He
    got fired a few months later.

    (I don't know if this is legal C; but it works fine with my compiler:

    c:\m>type fred.c
    #include <stdio.h>

    typedef void Take2Ints(int x, int y);

    Take2Ints SomeFunc{printf("%d %d\n", x, y);}

    int main(void) { SomeFunc(10, 20); }

    c:\m>bcc -r -q fred
    10 20
    )

    Yeah, I gues running it through `gcc` is a really heavy lift.
    <eyeroll>

    Yeah, you really just don't get it.

    One of us doesn't get it.

    I'm glad you can admit it.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Wed Oct 21 02:04:47 2026
    From Newsgroup: comp.lang.c

    On 20/10/2026 13:58, David Brown wrote:
    On 20/10/2026 13:41, bart wrote:

    But let us take a concrete example.  These network functions are from
    the LWIP network stack, which is designed to be used on small embedded systems that may not have any kind of OS - so it uses call-backs for asynchronous programming.

    An example API function is this :

    err_t dns_gethostbyname(const char *hostname, ip_addr_t *addr,
                            dns_found_callback found, void *callback_arg)

    The returned "err_t" can be "ERR_OK" (indicating the "hostname" is in
    the DNS cache and *addr is set to the IP), "ERR_ARG" for argument
    errors, or "ERR_INPROGRESS" to indicate that the stack is looking up the
    DNS name, and will call the callback when there is a final result or timeout.


    Without typedef's, that function signature would be something like :

    signed char dns_gethostbyname(const char *hostname, struct ip_addr
        *addr, void (*found)(const char *name,    const struct ip_addr
        *ipaddr, void *callback_arg), void *callback_arg);


    Do you expect anyone to believe you if you claim this is easier to read
    than the real declaration using typedefs?  I'll believe you if you say
    you find the original hard to read - but not if you claim the
    "untypedef'ed" version is clearer.

    Neither are great. But let's first lay them out better:

    err_t
    dns_gethostbyname(
    const char *hostname,
    ip_addr_t *addr,
    dns_found_callback found,
    void *callback_arg
    );

    Here, one problem is that there are 3 types that I don't know and would
    have to look up. The long version at least has all the info in one place:

    signed char
    dns_gethostbyname(
    const char *hostname,
    struct ip_addr *addr,
    void (*found)(const char *name, const struct ip_addr *ipaddr,
    void *callback_arg),
    void *callback_arg
    );

    That signed char return is unusual; why not 'int'? (How would you even
    print an 'err_t' value anyway)?

    That 'ip_addr_t' turns out to be a struct. For those I would use
    typedefs anyway; I rarely use struct tags and you have to invent an
    identifier in either case.

    Then we come to the function pointer, which is a quite a chunky one, but
    let's work with it. Here, I would question whether you really need those
    types in there, and especially those names.

    Presumably you have a regular function of your own with the same
    signature? You anyway never directly 'call' this parameter with
    arguments; you just pass it the address of your handler.

    Or do you use that typedef as documentation?

    Where does the info come from anyway; does the library export a suitable typedef? In that case you might as well use it. But if not, info must
    come from elsewhere.

    Anyway with some tweaks in place, using the struct typedef and using an
    inline function pointer type, it would look like this:

    signed char
    dns_gethostbyname(
    const char *hostname,
    IP_addr *addr,
    void (*found)(char*, IP_addr*, void *),
    void *arg
    );

    In this form, it is not wildly different from your short version.

    So I would look at other ways of tidying up before resorting to
    extraneous typedefs.

    But here, there may well be an extra reason to use a callback typedef; I
    don't have the full details.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@[email protected] to comp.lang.c on Tue Oct 20 18:23:32 2026
    From Newsgroup: comp.lang.c

    David Brown <[email protected]> writes:
    On 19/10/2026 23:27, Janis Papanagnou wrote:
    [...]
      * a b     PN (Polish Notation)

    There is no term "Polish Notation" - except as occasionally used to
    mean /postfix/ as a short form of "Reverse Polish Notation". RPN was invented, or at least popularised, by the Polish logician Jan
    Łukasiewicz (I admit to looking that up on Wikipedia!). There is no
    "PN" opposite.

    Yes, there most certainly is, and "* a b" is a good example of it.

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

    Jan Łukasiewicz invented what we now call Polish notation in 1924.
    `+ 3 4` is an example (which yields 7). Lisp syntax is more or
    less Polish notation with added parentheses. (I'm sure the phrase
    "more or less" is doing a lot of work.)

    Reverse Polish Notation, RPN, is very well known because it's
    used by some calculators, particularly those made by HP. It's a
    postfix notation. An example of RPN is `3 4 +` (which also yields 7).

    I've never seen the term "Polish Notation", without "Reverse", used
    to refer to postfix notation. PN is prefix; RPN is postfix.

    I see that Janis already pointed out your error. I'm disappointed
    that your followup did not acknowledge it. (I'm not commenting on the
    rest of what Janis wrote.)

    [...]
    --
    Keith Thompson (The_Other_Keith) [email protected]
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Wed Oct 21 02:39:27 2026
    From Newsgroup: comp.lang.c

    On 21/10/2026 01:56, Dan Cross wrote:
    In article <11b8qqg$3ejlp$[email protected]>, bart <[email protected]> wrote:
    On 20/10/2026 22:44, Dan Cross wrote:
    In article <11b8j17$3btus$[email protected]>, bart <[email protected]> wrote: >>>> On 20/10/2026 20:24, Dan Cross wrote:
    In article <11b7k22$2v8e5$[email protected]>, bart <[email protected]> wrote: >>>>
    The point is that the name you chose is meaningless to anyone
    other than you. What's a PCL? Phase Control Line? Printer
    Command Language? Photon Compressor Loop?

    Within the context of that application then it would be clear. You're
    just being overly hostile.

    Not really. You are, I presume, posting that code to try and
    make some kind of point about how "readable" it is. But it's
    not readable unless you already know what it does.

    What it does not relevant. This is simply defining an array of T. But
    because T happens to be a function pointer, DB insists that an alias
    must be created, and a new name invented.

    Why? Probably because in C, the syntax for function pointers gets hairy.

    I dunno; your syntax didn't seem any clearer to me.

    Yeah, the C is so much clearer. Of course, you would all lie through
    your teeth anyway before you'd admit mine might be simpler.

    I've just defined three entities: a variable, a function pointer, and a function, in both my syntax and in C's.

    Here are the first tokens of the C versions:

    int
    int
    int

    Can you guess which one is which yet?

    Here are the first three tokens in my syntax:

    int
    func
    ref

    Any easier? This is like PL Design 101.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@[email protected] to comp.lang.c on Tue Oct 20 18:55:57 2026
    From Newsgroup: comp.lang.c

    bart <[email protected]> writes:
    [...]
    Yeah, the C is so much clearer. Of course, you would all lie through
    your teeth anyway before you'd admit mine might be simpler.
    [...]

    You preemptively accuse someone of being a liar, and then you wonder
    why people are hostile to you.

    Tone down the insults and hyperbole.
    --
    Keith Thompson (The_Other_Keith) [email protected]
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@[email protected] (Dan Cross) to comp.lang.c on Wed Oct 21 01:56:44 2026
    From Newsgroup: comp.lang.c

    In article <11b954e$3hjvi$[email protected]>, bart <[email protected]> wrote:
    On 21/10/2026 01:56, Dan Cross wrote:
    In article <11b8qqg$3ejlp$[email protected]>, bart <[email protected]> wrote:
    On 20/10/2026 22:44, Dan Cross wrote:
    In article <11b8j17$3btus$[email protected]>, bart <[email protected]> wrote: >>>>> On 20/10/2026 20:24, Dan Cross wrote:
    In article <11b7k22$2v8e5$[email protected]>, bart <[email protected]> wrote: >>>>>
    The point is that the name you chose is meaningless to anyone
    other than you. What's a PCL? Phase Control Line? Printer
    Command Language? Photon Compressor Loop?

    Within the context of that application then it would be clear. You're >>>>> just being overly hostile.

    Not really. You are, I presume, posting that code to try and
    make some kind of point about how "readable" it is. But it's
    not readable unless you already know what it does.

    What it does not relevant. This is simply defining an array of T. But
    because T happens to be a function pointer, DB insists that an alias
    must be created, and a new name invented.

    Why? Probably because in C, the syntax for function pointers gets hairy.

    I dunno; your syntax didn't seem any clearer to me.

    Yeah, the C is so much clearer. Of course, you would all lie through
    your teeth anyway before you'd admit mine might be simpler.

    Oh, grow up.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From gazelle@[email protected] (Kenny McCormack) to comp.lang.c on Wed Oct 21 07:22:49 2026
    From Newsgroup: comp.lang.c

    In article <11b963d$3h5oi$[email protected]>,
    Keith Thompson <[email protected]> wrote:
    bart <[email protected]> writes:
    [...]
    Yeah, the C is so much clearer. Of course, you would all lie through
    your teeth anyway before you'd admit mine might be simpler.
    [...]

    You preemptively accuse someone of being a liar, and then you wonder
    why people are hostile to you.

    Tone down the insults and hyperbole.

    The Lord and Master has spoken.

    All must comply with His dictates.
    --
    Just like Donald Trump today, Jesus Christ had a Messiah complex.

    And, in fact, the similarities between the two figures are quite striking.
    For example, both have a ragtag band of followers, whose faith cannot be shaken.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From fir@[email protected] to comp.lang.c on Wed Oct 21 11:19:23 2026
    From Newsgroup: comp.lang.c

    Lawrence D’Oliveiro pisze:
    t to end each case-sequence in a switch statement with
    a break-statement: put the break at the same indentation level as the case-clause as well as the switch-expression. That way, you can scan
    your eye down a single line f

    some time ago i was saying what the proper switch should like
    (imo, but im not sure if my conclusions are anough to take is a s proven)

    case {} case {} case {} otherwise {}

    its indeed sorta needed becouse case in fact are ifs
    (not if-elses) (so some in fact could write

    if {} if {} if {} otherwise {}

    its the same)

    the problem is you got no group alse
    and here this otherwise need to check all ifs
    "or" them and use group else for them

    this could be written in few ways, but my case case case otherwise names it could also do


    if {} or if {} or if {} else {}

    so either you need logic operators here or predefined constructs like otherwise (maybe both)

    and that should be included not switch wchich is bad imo


    other way is to define distionary more as data construct

    dict {
    'mental' {/* 1 */}
    'reductionists' {/* 2 */}
    'suck' {/* 3 */}
    }

    then you could use

    dict('reductionists')

    to yeld to /* 2 */

    this second one parallels to switch keyword


    so c switch mixes them both in bad way..they should be spitet and
    upbuild as showed ;c

    thats my conclusion as switch topic as far by now ;c












    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@[email protected] to comp.lang.c on Wed Oct 21 11:20:05 2026
    From Newsgroup: comp.lang.c

    On 20/10/2026 22:07, bart wrote:
    On 20/10/2026 16:02, David Brown wrote:
    On 20/10/2026 16:11, bart wrote:

    The other was C. There, several choices were made:

    * To start with that Fortran style except that [] are used

    * To decree that that 'A[20]' syntax is supposed to match indexing of
       A as it might appear in an expression

    * To introduce "*" as a prefix dereference operator in expressions ...

    * ... which then means that a prefix "*" appears in the declaration too

    * A further complication was to allow function pointers within that a
       declaration list

    I don't see a problem with that.  If you need to declare a function
    pointer, you need to declare it in a declaration list.

    To me, the big disadvantage of C's declaration syntax is that it lets
    you declare things of different (but related) types in the same
    declaration.

    Yes, but that doesn't bite so much because it is uncommon.


    Unfortunately not - but it is uncommon to mix objects and function declarations, or objects of wildly different real types.

    or, more common and therefore worse :

         int * a, b;

    (See below.)

    * Yet one more which came later was to add 'const', where placement now
       gets confusing

    Some people do find it hard to understand the difference between :

         const int * p;
         int * const q;
         const int * const r;

    I note that this is despite the clear left-to-right nature of "const"
    here.
    I was going to say it was right-to-left, but it can be considered both
    and thus not clear:

        const int const * const p;
          1         2       3

    const 1 applies to the basetype to its right.
    const 2 applies to the basetype to its left.

    These are redundant - they do the same thing. (I'd have preferred if
    the ordering rules were strict - allowing only "const int" or "int
    const" - but at least people are usually consistent in their style.)


    (Both also can be in the middle with compound types like 'long long'!)

    const 3 is tricky: I think it applies to the * to its left, since it
    says that the pointer value itself is const. But 'p' has type 'pointer
    to', so it could apply to that directly.

    Yes - it is "p" that is const, not the "*".


    What about this however:

       int * const *  p;

           1   2   3

    I think here, const 2 applies to * 1, which is to it's left, and can't
    apply to 'p' as that is the other side of the * 3.

    *p is of type "int * const" - thus you can use "*p" to access a pointer-to-int, but you can't use *p to change that pointer-to-int.

    Fortunately, such types are rare.


    Fair to say that is a complete mess, and it is error prone.

    No, it is not at all fair to say that. It is fair to say that a
    different way of writing types might make it easier to understand - but
    that's a /long/ way from saying it is "a complete mess". And you can't
    call it "error prone" unless you know that people regularly use such declarations, and often have bugs in their code as a result of doing so incorrectly. I think that is an unrealistic claim.

    I appreciate that it can be difficult to see exactly what that type
    means, unless you use such a construct regularly - but there is no
    benefit in wild exaggeration. And I don't think /any/ alternative
    syntax would make it easy to understand what that type really is, what
    it can do and what it cannot do, or why you might want it.


    With a LTR syntax that a postfix deref would achieve, 'const' would
    always be written immediately to the left of any * modifiers. (It is meaningless for arrays and functions.)

    You can write this in C++ :

    // This bit is only needed once
    template <typename T> using ptr = T *;

    // p is a pointer to a const pointer to an int
    ptr<const ptr<int>> p;


    That's LTR syntax. Sure, it also has < > parentheses, but that's a
    minor point since the ordering of the components is what apparently
    matters so much.


    Or you can write :

    typedef int * p_int;
    const p_int * p;

    Thus p is a pointer to a "const p_int", where a "p_int" is a pointer to
    an int.

    These are different ways to write the same type, including one that is
    LTR, and the main hinder to understanding remains the same - what is the
    type for?


    It is never applied directly to a variable name.

    For base types, it can be applied on the left, but C would still allow
    it on the right or in the middle, or all three with duplicates.

    What do you mean "base types" ? Do you mean that C lets you write

    const long int a;
    long const int a;
    const int long a;
    int const long a;
    long int const a;
    int long const a;

    ?

    If that's your complaint, then I agree with that one - I would be
    happier if C had allowed only "const long int;" here. But I think most programmers are consistent in the style they use (though some prefer
    "east const").


    That means there would be an ambiguity here where there is no identifier between 'int' and 'const':

       (const int const *)

    For such reasons I would restrict base type const to be only on the left.)
    Complicated types are a minority.

    I've showed even simple types or trying to use 'const' get becomes confusing.

    No, you haven't.

    You have shown that /you/ claim to be confused by types with "const".
    Most C programmers, once they are used to the language, do not find it confusing in common and simple types.

    You do not get to invent meaningless complicated types, claim that you
    don't understand them, and use that as evidence that C's declaration
    syntax is "a complete mess".

    At best, all you can show is that for complex types, C's syntax can
    require more thought to write or understand than some alternative
    syntaxes might. But we've all known that for decades.



    So, PARENTHESES HAVE BEEN ELIMINATED for purpose of disambiguating
    array/pointer and pointer/array, both within expressions and within
    type-declarations.

    Agreed.

    But does that make a significant difference?  I don't think so.

    It would make a HUGE difference:

    Your points below are all true, but IMHO all very minor, and do not add
    up to anything much. They might be enough to tip the balance when
    developing a new language where you are trying to decide whether your dereference operator should be prefix or postfix, but they are not
    enough to cause any concern in a language that has chosen prefix.


    (1) It helps to fix that confusion above

    Your invented confusion.


    (2) You don't need parentheses so no need to remember if you want
        (*A)[] or *A[]. Those will disappear from expressions too; less
        clutter all round.

    That doesn't matter in practice.


    (3) It simplifies indexing of pointer-to-array from (*A)[i] to A*[i], so
        that actual array pointers, which are more type-safe, could start to
        appear more in C rather than the current T* idiom

    I don't see that as significant.

    I do agree that the decay of expressions using array types into pointer
    types is a source of error in C code - though I do not think it is as
    bad as you do. I would have been happier if arrays were value types and
    the expressions did not decay to pointer expressions without manual intervention (like taking the address of the first element). In my C++
    code, I make a lot of use of std::array<> types for that purpose - in my
    C code, it is not uncommon for me to have arrays wrapped in a struct.

    But I just don't see pointer-to-array expressions to be common enough
    for the difference you describe to be important.


    (4) For pointers to structs, these are the patterns:

        prefix *    With ->    With postfix *

        (*P).m      P->m       P*.m
        (**P).m     (*P)->m    P**.m
        (***P).m    (**P)->m   P***.m

    Which column looks the tidiest?

    Far and away the most common - by orders of magnitude - are pointers to structs. "p->m" looks fine to me, and I prefer it to "p*.m". A pointer
    to a pointer to a struct is rare enough that it is a good thing for the
    syntax to stand out - with a postfix dereference, I'd probably still use parentheses and write "(p*)->m".


    (5) With prefix *, a pointer type looks like 'T*'; notice the * is on
        the right, not left! With postfix *, it would all be consistent. You
        also wouldn't have 'T*A'; that would be an error (T* only happens
        when there is no name)

    The C declaration syntax is "declaration follows use". If "*" were a
    postfix operator, then the declaration of a pointer-to-int would become:

    int p*;

    while the type of p would be "int *". So you would still have an inconsistency there, unless you also changed the way C has its declarations.


    (6) Your 'int * a, b' example would become:

      int a *, b;

    Much easier, even with that space, to see that '*' does not belong to
    the base type but is a modifier for that variable.

    It's still bad. I don't think finding a way to make it easier to write
    bad code is a good idea.


    It doesn't fix everything, so you'd still have this:

       int p* = &a;
           p* = a;

    To fix this requires that all modifiers apply to the base type. But this would be a massive change. The above is merely what happens when *
    becomes postfix.

    So basically, the suggestion would change some very minor things -
    mostly in subjective ways - and not actually do anything for aspects of
    the language where there is more of a consensus that C is sub-optimal.
    And for this, you would want a fundamental change to one of the most
    used operators in all C code!


    A mistake that could so easily have been avoid by choosing a
    different precedence as shown above. Did none of the thousand people
    working at Bell Labs (according to a comment in DC's follow-ip) spot
    this and say anything?

    I suspect the folks at Bell Labs were too busy writing real code to be
    bothered by how confused you would be with artificially complex types.

    So you agree the process was very different compared to that which lead
    to Ada for example? Just a couple of guys left to do their own thing.

    I don't see how you reach that conclusion from what I wrote.

    It is, however, true that C was designed by a small number of people
    working closely together, rather than a large committee-based design
    process involving lots of people.


    (Maybe they were respected enough that no one dared to offer any constructive criticism, or if they did then it was dismissed. As happens here.)

    I have no insight into the culture at Bell Labs at the time, but that
    sounds extraordinarily unlikely.

    Feel free to offer some constructive criticism some time, and we will
    see if it is dismissed. Note that "constructive criticism" involves
    more than "It's C, and I hate everything about C because it is connected
    to *nix, and I hate everything about *nix because it is connected to C".
    And even if you occasionally have a valid criticism about C, it is not "constructive" criticism because we did not design the language, and we
    do not dictate how it could be changed or how it is used.



    (ACTUALLY IT IS NOT TOO LATE. A secondary postfix deref op could have
    been added. This could have been done 50 years ago, with the original
    eventually deprecated.

    It /is/ too late - far, far too late.  It would be a terrible idea to
    add a new postfix dereference operator to give two different operators
    with no benefit other than very occasionally reducing the need for
    parentheses.

    But a special operator P->m to do the same job as (*P).m was fine! The
    new op would eliminate the need for ->.


    The -> operator was added to C in 1972 ! It is not new - it has always
    been part of the language beyond its early prototype versions.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@[email protected] to comp.lang.c on Wed Oct 21 12:45:31 2026
    From Newsgroup: comp.lang.c

    On 21/10/2026 02:05, Keith Thompson wrote:
    David Brown <[email protected]> writes:
    [...]
    Without typedef's, that function signature would be something like :

    signed char dns_gethostbyname(const char *hostname, struct ip_addr
    *addr, void (*found)(const char *name, const struct ip_addr
    *ipaddr, void *callback_arg), void *callback_arg);

    I might write that as:

    signed char dns_gethostbyname(
    const char *hostname,
    struct ip_addr *addr,
    void (*found)(
    const char *name,
    const struct ip_addr *ipaddr,
    void *callback_arg
    ),
    void *callback_arg
    );

    so the indentation and structure reflects the semantics. I find
    that much clearer than your version. (I'm not commenting on the
    merits of typedefs.)


    Certainly the indentation makes the unpleasant non-typedef'ed version
    clearer. And /if/ I had to write that function signature without
    typedefs, I would structure it like you had - but I can't think of any
    reason I would ever have to do so.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@[email protected] to comp.lang.c on Wed Oct 21 13:21:58 2026
    From Newsgroup: comp.lang.c

    On 21/10/2026 03:04, bart wrote:
    On 20/10/2026 13:58, David Brown wrote:
    On 20/10/2026 13:41, bart wrote:

    But let us take a concrete example.  These network functions are from
    the LWIP network stack, which is designed to be used on small embedded
    systems that may not have any kind of OS - so it uses call-backs for
    asynchronous programming.

    An example API function is this :

    err_t dns_gethostbyname(const char *hostname, ip_addr_t *addr,
                             dns_found_callback found, void *callback_arg)

    The returned "err_t" can be "ERR_OK" (indicating the "hostname" is in
    the DNS cache and *addr is set to the IP), "ERR_ARG" for argument
    errors, or "ERR_INPROGRESS" to indicate that the stack is looking up
    the DNS name, and will call the callback when there is a final result
    or timeout.


    Without typedef's, that function signature would be something like :

    signed char dns_gethostbyname(const char *hostname, struct ip_addr
         *addr, void (*found)(const char *name,    const struct ip_addr >>      *ipaddr, void *callback_arg), void *callback_arg);


    Do you expect anyone to believe you if you claim this is easier to
    read than the real declaration using typedefs?  I'll believe you if
    you say you find the original hard to read - but not if you claim the
    "untypedef'ed" version is clearer.

    Neither are great. But let's first lay them out better:

     err_t
        dns_gethostbyname(
          const char *hostname,
          ip_addr_t  *addr,
          dns_found_callback found,
          void       *callback_arg
        );

    OK. I'd not write it that way, and I don't think it is better, but
    that's a subjective opinion.

    (As a note on layout, the original code is not as line-length restricted
    as a Usenet post, and the code has Doxygen comments. That means that
    there is additional comment information in header, and that the user documentation, which is the normal way to get details of the API, is
    generated html.)


    Here, one problem is that there are 3 types that I don't know and would
    have to look up.

    Incorrect.

    There are three types that are not standard C types, but if you are
    using this function, you don't have to look them up. You generally
    don't need to know what they are - indeed, knowing their details can
    easily lead to writing poorer and less adaptable or portable code. Only information about the callback function type is of interest, and even
    then it is only marginal - you look it up once when writing an
    appropriate callback function, taking negligible effort compared to
    writing the code itself. And because it is a named type, you know
    immediately that your function is suitable for other use-cases of that specific named type, such as for related dns lookup APIs.

    The long version at least has all the info in one place:

     signed char
        dns_gethostbyname(
          const char     *hostname,
          struct ip_addr *addr,
          void (*found)(const char *name, const struct ip_addr *ipaddr, void *callback_arg),
          void           *callback_arg
        );

    That signed char return is unusual; why not 'int'? (How would you even
    print an 'err_t' value anyway)?

    It seems that yet again, you need an explanation of fundamental points
    of software development. Today's lesson is on "abstraction".

    It does not matter what type "err_t" is, underneath. What matters is
    what you can /do/ with it. It is a type that is returned by this
    function (and many others), and which can be compared to ERR_OK, ERR_INPROGRESS, and ERR_ARG. That's all you need to know to use it here.

    Maybe on some targets (of this portable library), err_t is "signed
    char". Maybe on others it is "int32_t". Maybe in a newer version of
    the library, it will be an enum.

    It is also nice to know that it can be used in a switch, and cast to an
    int for printf.

    The documentation for the type can give more or less detail about it.
    But it is /not/ the same as a "signed char". That is an implementation
    detail which you should not rely on, and it is better - clearer, safer,
    more portable, more maintainable - if you do not know what it is. (I
    didn't know, until looking it up for these posts.) You use the correct
    type, as documented.


    Or look at the "ip_addr_t" type. It happens, at the moment, to be a
    struct. But it might have been a union. The size and contents of the
    struct depend on details of how the library is built - whether it has
    support for ipv4, ipv6, or both. Maybe a future version will also
    support ipv8, or ipv5 (I've heard some people are trying to make an IP protocol that covers more than IPv4, but without most of the
    complicating additional features of IPv6). It is an abstract type - you
    use it without knowing the details.



    That 'ip_addr_t' turns out to be a struct. For those I would use
    typedefs anyway; I rarely use struct tags and you have to invent an identifier in either case.

    Then we come to the function pointer, which is a quite a chunky one, but let's work with it. Here, I would question whether you really need those types in there, and especially those names.

    Presumably you have a regular function of your own with the same
    signature? You anyway never directly 'call' this parameter with
    arguments; you just pass it the address of your handler.

    Yes, that is how callbacks work.


    Or do you use that typedef as documentation?

    You can certainly do that if you want, in a declaration of the function
    - but it would be unusual to do so in the definition. The typedef is
    used primarily when passing the function pointer around, or storing it
    (in a local variable, in a struct, or whatever).


    Where does the info come from anyway; does the library export a suitable typedef? In that case you might as well use it. But if not, info must
    come from elsewhere.

    Of course it "exports" the typedef - it is in one of the library's headers.


    Anyway with some tweaks in place, using the struct typedef and using an inline function pointer type, it would look like this:

     signed char
        dns_gethostbyname(
          const char *hostname,
          IP_addr    *addr,
          void      (*found)(char*, IP_addr*, void *),
          void       *arg
       );

    In this form, it is not wildly different from your short version.

    Not wildly different, just worse by counter-productively removing the abstractions and appropriate type names, and uselessly cluttering the declaration with unnecessary detail.


    So I would look at other ways of tidying up before resorting to
    extraneous typedefs.

    But here, there may well be an extra reason to use a callback typedef; I don't have the full details.



    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@[email protected] (Dan Cross) to comp.lang.c on Wed Oct 21 11:26:55 2026
    From Newsgroup: comp.lang.c

    In article <11ba78m$3peq3$[email protected]>,
    David Brown <[email protected]> wrote:
    On 21/10/2026 03:04, bart wrote:
    [snip]
    Anyway with some tweaks in place, using the struct typedef and using an
    inline function pointer type, it would look like this:

     signed char
        dns_gethostbyname(
          const char *hostname,
          IP_addr    *addr,
          void      (*found)(char*, IP_addr*, void *),
          void       *arg
       );

    In this form, it is not wildly different from your short version.

    Not wildly different, just worse by counter-productively removing the >abstractions and appropriate type names, and uselessly cluttering the >declaration with unnecessary detail.

    ...and also removing the `const` qualifiers on the first two
    pointer arguments to `found`.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Wed Oct 21 12:29:45 2026
    From Newsgroup: comp.lang.c

    On 21/10/2026 10:20, David Brown wrote:
    On 20/10/2026 22:07, bart wrote:
    On 20/10/2026 16:02, David Brown wrote:
    On 20/10/2026 16:11, bart wrote:

    * A further complication was to allow function pointers within that a
       declaration list

    To me, the big disadvantage of C's declaration syntax is that it lets
    you declare things of different (but related) types in the same
    declaration.

    Yes, but that doesn't bite so much because it is uncommon.


    Unfortunately not - but it is uncommon to mix objects and function declarations, or objects of wildly different real types.

    That's what I meant.

         const int const * const p;
           1         2       3

    const 1 applies to the basetype to its right.
    const 2 applies to the basetype to its left.

    These are redundant - they do the same thing.  (I'd have preferred if
    the ordering rules were strict - allowing only "const int" or "int
    const" - but at least people are usually consistent in their style.)


    (Both also can be in the middle with compound types like 'long long'!)

    const 3 is tricky: I think it applies to the * to its left, since it
    says that the pointer value itself is const. But 'p' has type 'pointer
    to', so it could apply to that directly.

    Yes - it is "p" that is const,  not the "*".

    I would disagree. This type can also be written as:

    (const int const * const)

    There is no 'p' to apply to. The type describes a pointer to an integer.
    The first two consts say, redundantly, that the integer value is const.

    The third must then apply to the pointer.


    What about this however:

        int * const *  p;

            1   2   3

    I think here, const 2 applies to * 1, which is to it's left, and can't
    apply to 'p' as that is the other side of the * 3.

    *p is of type "int * const" - thus you can use "*p" to access a pointer- to-int, but you can't use *p to change that pointer-to-int.

    But what exactly does this 'const' apply to?

    I'm suggesting any 'const' applies either to the base type (the one on
    the left) or to a particular '*'.

    In that case the latter 'const's must apply right-to-left to the
    preceding '*'.

    Fair to say that is a complete mess, and it is error prone.

    No, it is not at all fair to say that.  It is fair to say that a
    different way of writing types might make it easier to understand - but that's a /long/ way from saying it is "a complete mess".  And you can't call it "error prone" unless you know that people regularly use such declarations, and often have bugs in their code as a result of doing so incorrectly.  I think that is an unrealistic claim.

    If there's any confusion about which const applies to which type
    element, then mistakes can be made.

    You can write this in C++ :

        // This bit is only needed once
        template <typename T> using ptr = T *;

        // p is a pointer to a const pointer to an int
        ptr<const ptr<int>> p;


    That's LTR syntax.  Sure, it also has < > parentheses, but that's a
    minor point since the ordering of the components is what apparently
    matters so much.

    That it is LTR is now irrelevant because I find that incomprehensible
    anyway. You've turned a linear chain a nested structure ... oh never
    mind, I don't even want to go there with C++.

    Or you can write :

        typedef int * p_int;
        const p_int * p;

    Thus p is a pointer to a "const p_int", where a "p_int" is a pointer to
    an int.

    So, a common pattern with you is to use workarounds so that you
    effectively emulate LTR type patterns. Because they are easier to work
    with and understand.

    So you do appreciate how they facilitate things, even though they
    introduce an extra level of indirection and also disseminate the type information across the program.

    But you want to underplay how useful it would be to have natural LTR
    type declarations within a syntax.

    These are different ways to write the same type, including one that is
    LTR, and the main hinder to understanding remains the same - what is the type for?

    If you create a type alias voluntarily (I don't mean structs where
    either a tag or a typedef needs to be created) then yes the name should
    impart something useful.

    But in my view this is often taken too far. Sometimes you have structs
    where every member has a different user-type. When you look further, you
    find they are all ints. That is just obfuscation.

    (I would accept enumeration types if the compiler can employ that info
    to improve type safety, but that seems to be limited.)

    I've showed even simple types or trying to use 'const' get becomes
    confusing.

    No, you haven't.

    OK. That is not surprising.

    It would make a HUGE difference:

    Your points below are all true, but IMHO all very minor, and do not add
    up to anything much.

    It would eliminate half the issues with C's type syntax. Probably CDECL wouldn't need to exist. Lots of () disappear. It would make
    pointers-to-arrays more viable.

    But that's nothing in your view. OK again.

    Your invented confusion.


    That doesn't matter in practice.

    I don't see that as significant.

    I do agree that the decay of expressions using array types into pointer types is a source of error in C code - though I do not think it is as
    bad as you do.

    I didn't say anything about, and that wouldn't be affected.


    But I just don't see pointer-to-array expressions to be common enough
    for the difference you describe to be important.


    If you're passing arrays to a function by-reference then the natural way
    is to a have a pointer to the array. C can do that, but nobody ever does
    so, probably because indexing is then so ugly.

    With my idea, (*A)[i] turns into A*[i], a bit less ugly.

    (In my language, it was A^[i]. However, some years ago I relaxed the
    rules to allow such in-between derefs to be dropped - the compiler will reinsert them as needed.

    So indexing looks like A[i], and there is the extra type safety of
    working with actual arrays, not pointers to things that may or may not
    be arrays.

    But then I also have pass-by-reference which achieves the same thing.)

    (4) For pointers to structs, these are the patterns:

         prefix *    With ->    With postfix *

         (*P).m      P->m       P*.m
         (**P).m     (*P)->m    P**.m
         (***P).m    (**P)->m   P***.m

    Which column looks the tidiest?

    Far and away the most common - by orders of magnitude - are pointers to structs.  "p->m" looks fine to me, and I prefer it to "p*.m".

    But where's the consistency? Sometimes "." is used for member selection,
    and sometimes "->". And with two pointer levels, you need both!

    (Again in my language, all those * (or ^) in the right column can be
    dropped. Some loss of transparency, but much, much cleaner code.

    But TBF, this could also be done in C without needing postfix *.)


    (5) With prefix *, a pointer type looks like 'T*'; notice the * is on
         the right, not left! With postfix *, it would all be consistent. You
         also wouldn't have 'T*A'; that would be an error (T* only happens >>      when there is no name)

    The C declaration syntax is "declaration follows use".  If "*" were a postfix operator, then the declaration of a pointer-to-int would become:

        int p*;

    while the type of p would be "int *".  So you would still have an inconsistency there, unless you also changed the way C has its
    declarations.

    The point is that currently you have 'int*' for the type, '*p' to
    declare p, and '*p' in expressions. The '*' switches sides for the bare
    type!

    (6) Your 'int * a, b' example would become:

       int a *, b;

    Much easier, even with that space, to see that '*' does not belong to
    the base type but is a modifier for that variable.

    It's still bad.  I don't think finding a way to make it easier to write
    bad code is a good idea.

    It wouldn't stay bad for long! Because if the intention was to declare
    two pointers, then it's easier to see that this is wrong.

    So basically, the suggestion would change some very minor things -
    mostly in subjective ways - and not actually do anything for aspects of
    the language where there is more of a consensus that C is sub-optimal.
    And for this, you would want a fundamental change to one of the most
    used operators in all C code!

    Obviously you can't change prefix * now. A postfix /alternative/, in
    addition to prefix *, could have been introduced decades ago. So by the
    time /you/ encountered C, you might have been using the latter.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Wed Oct 21 12:33:57 2026
    From Newsgroup: comp.lang.c

    On 21/10/2026 12:21, David Brown wrote:
    On 21/10/2026 03:04, bart wrote:

    Where does the info come from anyway; does the library export a
    suitable typedef? In that case you might as well use it. But if not,
    info must come from elsewhere.

    Of course it "exports" the typedef - it is in one of the library's headers.

    You could have said that in the first place. So it's not really a choice
    then is it?

    Then it makes sense to use what they have provided.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@[email protected] to comp.lang.c on Wed Oct 21 14:17:38 2026
    From Newsgroup: comp.lang.c

    On 20/10/2026 21:24, Dan Cross wrote:
    In article <11b7k22$2v8e5$[email protected]>, bart <[email protected]> wrote:
    On 20/10/2026 09:01, David Brown wrote:
    On 19/10/2026 23:28, bart wrote:

    (Funny that when I suggest that nested loop breaks are uncommon,
    everyone says I'm wrong! Some even write 200-line made-up examples to
    prove their point.)

    I don't remember "everyone" saying you were wrong to say that nested
    loop breaks are uncommon - in fact, I don't remember /anyone/ saying
    that was wrong.

    (There was a LOT of antipathy towards my idea to fix the common case of
    'loop-break' clashing with 'switch-break', BECAUSE it did not fix the
    problem of nested loop-break, which is uncommon, even though that wasn't
    the aim.)

    Those are two different things. No one disagrees with you that
    "nested break from a switch inside of a loop" is relatively more
    common than other variants.


    Quibble - that is not established to my satisfaction. I am not
    convinced that wanting a nested break for "switch inside loop" is more
    common than wanting it for "loop inside loop". So I neither agree nor disagree with that claim. I don't, however, think it matters much -
    both are situations that turn up sometimes in code, and definitive
    answers are neither possible nor useful.

    Using that as an excuse not to provide a more general mechanism
    because you already have a proposal for the specific case is
    what I and others took you to task for. I find this ironic,
    since you rail against things in C that you do not like, citing
    the most ridiculous examples you can think of that do not show
    up in actual programs, yet for something where it is pointed out
    to you that your solution does not generalize, you claim that it
    does not need to because ... the general case rarely shows up in
    a real program.

    There is no reason to abstract away that function pointer type.

    You probably do so in C /because/ the type involves * () and [] but
    have somehow persuaded yourself that it just better that way.

    Do you hear that whooshing noise?  It is the sound of the point flying
    far above your head.

    Here is an example of some sensible function typedefs, all from third-
    party code (so not my "peculiar" style)

    typedef void (*TimerCallbackFunction_t)( TimerHandle_t xTimer );

    TimerHandle_t xTimerCreate(  const char * const pcTimerName,
                     TickType_t xTimerPeriodInTicks,
                     UBaseType_t uxAutoReload,
                     void * pvTimerID,
                     TimerCallbackFunction_t pxCallbackFunction );

    typedef void (*lwip_thread_fn)(void *arg);
    typedef void (*tcpip_init_done_fn)(void *arg);
    typedef void (*tcpip_callback_fn)(void *ctx);
    typedef void (* sys_timeout_handler)(void *arg);
    typedef void (*dns_found_callback)(const char *name,
                     const ip_addr_t *ipaddr, void *callback_arg);

    This is the kind of C I find hard to read. There are lots of typedefs
    but few uses of those typedefs that I can see, so I don't know how much
    difference they make.

    You again missed the entire point. You may not see many uses
    of them, but as David says, the `typedef`s give you
    domain-specific *names* understandable to the programmer: a
    programmer can see the `sys_timeout_handler` type instantly know
    that this has a different function than the,
    `tcpip_callback_fn`, despite the having the same type.

    Exactly.


    The other point is that the ridiculous examples you make up to
    illustrate your distaste for C declaration syntax basically do
    not appear in real programs.

    [snip]
    I've left in the regular parameter names, even though C doesn't need
    them, but they are quite heavy - you don't really need those
    Hungarian-style prefixes.)

    Well, I guess this buys you one thing: the parameter name for the last
    parameter is to the right of its type, rather than be inside it. But a C
    expert should not be fazed by that.

    Here is the same function as I might write it in an alternative syntax.

    I've kept the same names, but changed case-style and removed prefixes
    and suffixes. I've capitalised user-type names:

    func TimerCreate( # (retain case if FFI import)
    ichar timername,
    Ticktype timerperiodinticks,
    Ubasetype autoreload,
    ref void timerid,
    ref proc(Timerhandle) callbackfn)

    In this form, it's hard to see what benefit a typedef would give for
    that last parameter; it is simple enough.

    What is your point? Do you have one? If you don't want to use
    C, don't use C.

    There are plenty of languages that can do this kind of thing
    that are not C and have syntax and semantics closer to what you
    seem to want. Here's an example in Rust:

    pub trait TimerHandle { ... }

    fn CreateTimer<T>(
    timer_name: &str,
    period: std::time::Duration,
    auto_reload: bool,
    timer_id: T,
    handler: fn(&dyn TimerHandle),
    ) -> Result<Timer<T>, TimerError>

    I didn't know what an `UBaseType_t` is, and while "autoreload"
    sounded pretty intuitive, I wasn't sure about the semantics, so
    I looked it up (the example comes from `FreeRTOS`). In this
    context, it is a boolean saying whether the timer should repeat
    with the given periodicity, or whether it is a one-shot.

    FreeRTOS is written in C90 - a mistake, IMHO - and thus does not use
    bool. Instead, it uses constants pdTRUE and pdFALSE of type
    UBaseType_t. UBaseType_t is a type that is dependent on the target -
    usually it is either 16-bit or 32-bit. But of course it doesn't matter
    what the underlying types are - you use the typedef names, and the
    documented constants.


    The timer_id is opaque to the timer, and it looks like it's used
    to facilitating the handler accessing timer-specific data. In
    C, passing it as a `void *` is used as a way to get a poor-man's
    overloading. But Rust has generics, I just made it generic over
    some type T.

    FreeRTOS uses "void *" to mean "pointer to internal structure that you shouldn't be messing with". It uses this far too often, and is, IMHO, a
    poor design choice. (I also dislike the silly Hungarian naming.) I
    would much preferred if there had been :

    struct Internal_Timer_Struct;
    typedef struct Internal_Timer_Struct * timer_id_t;

    and then the parameter "timer_id_t timer_id". So in a re-write, it
    would not be a generic. (You might choose to use a generic for the
    handler function type, so that handler callbacks could have parameters
    of other types, but not for the timer id.)

    I am using these declarations from FreeRTOS (and LWIP) to demonstrate
    the use of function typedefs in massively popular codebases, not to
    claim FreeRTOS is a paradigm of C code design!


    If I were writing this from scratch in Rust, a language that has
    generics, closures, and so sum types, I'd do the whole thing
    differently; see the end for an example.

    But I digress. The point here is, Bart, that alternatives exist
    if you don't like C. You don't have to keep posting, over and
    over again, in comp.lang.c of all places, about how oh so
    terribly awful C is. If you don't want to program in C, simply
    don't program in C.

    Ask yourself why the typedefs are used.  Look at the /names/.  Those
    last four are all from the same network stack library, and are all
    typedefs for "void (*)(void*)".

    Until you mentioned it, I hadn't noticed. So typedef has done a good job
    of hiding that useful fact! But looking more closely, it is the first
    four of the last five.

    Let's take one:

    typedef void (*lwip_thread_fn)(void *arg);

    That 'arg' is not much use for a start (other than being a hint that
    this particular (...) is where the parameters go).

    So, maybe this is used like this:

    void F(lwip_thread_fn lwip_thread_callback);

    I have no idea what you're trying to say here. The obvious (and
    honestly, excusable) syntax error aside, what is F? It's a
    function that, what, takes two function pointers?

    The type defined by `lwip_thread_fn` is a pointer to a function
    that takes a void pointer (`void *`) as its sole arugment, and
    returns `void` (that is, has no meaningful return value).

    Intuitively, the name implies that this is the function run as
    some thread, so we'd pass it to a thread creation function. The
    usual shape of those things is to give them a pointer to some
    function to run in the new thread, and a pointer to some
    arguments to be passed to that function.

    Yes.

    For example:

    void
    whatever(void *argp)
    {
    struct Args *args = argp;
    while (keep_running()) {
    // Do the thing the thread is supposed to do.
    }
    thread_exit(SUCCESS);
    }

    thread_t *
    start_the_whatever_thread(void)
    {
    struct Args *args = malloc(sizeof(*args));
    if (args == NULL) abort();
    memset(args, 0, sizeof(*args));
    args->whatever = something();
    // etc...
    thread_t *thr = thread_create(whatever, args);
    if (thr == NULL) abort();
    return thr;
    }

    Something could start this as:

    thread_t *whatever_id = start_the_whatever_thread();

    At some point later, if you want to wait for the thread to
    exit, you'd run:

    (void)thread_join(whatever_id);

    Note this is decently complex behavior, but it's actually quite
    intuitive from the name and the type.


    You have got a very clear picture here, much of it from the names of the types. For a Rust programmer, you give a good impression of experience
    with C :-)

    The only mistake you made is that programmers working on systems using FreeRTOS and the like, have a fear and loathing of "malloc", have never
    heard of "abort()", and do not join our threads because they all run
    until the power is switched off.

    Here you have two identifiers imparting the sort kind of information; a
    tautology.

    That's not what a tautology is.

    If that function pointer pattern is common, or recurs in a suite of
    functions, I might also have used a typedef, but with a common name.

    Then you loose the domain specificity; you can't tell from the
    name whether you need an LwIP thread, or a callback, or a
    something run in a different thread, or just a plain 'ol
    function you want to apply to run every now and again for a side
    effect.

    Precisely.


    Then only one would be needed, say:

    typedef void (*stack_callbackfn)(void);

    I might have done the same in that alternate syntax as it would start to
    get cluttery: 'ref proc(ref void)', but also in order to define that
    common pattern in one place.

    I dunno. Sounds like you have no idea what the code that David
    posted is meant to do. But that's a "you" problem.

    Note that 'pcl' in my example /is/ a typedef; here it makes sense as
    it is used in 100s of places. This function pointer occurs in only one >>>> place.

    I'm sorry, I had mistaken you for a programmer who wanted to write good, >>> clear programs.  Naming things is not a shortcut to save keypresses.

    Isn't that one of the main uses of typedefs? So as to give a handy,
    'euphonious' one-token alias to an elaborate typedef.

    It also allows you to change the type in one place without having to
    update hundreds of instances.

    It also allows the type to be opaque.

    The point is that the name you chose is meaningless to anyone
    other than you. What's a PCL? Phase Control Line? Printer
    Command Language? Photon Compressor Loop?

    Saving keypresses is bonus benefit, but if it is shorter, then it can
    also help readability as other critical elements are not overshadowed.

    So I'm not sure what objection you have to this particular use of it.

    Have you ever written a large program that was maintained by
    anyone other than yourself?

    Here is the one place I do remember using typedef for a function pointer
    (from an old project, not in C):

    type fnptr = ref proc

    repeat
    (fnptr(pcptr^))^()
    until stopped

    It's used as a cast, but reason I have it is because with simple cast
    syntax, which is 'T(X)', the meaning without it would be ambiguous (a
    grammar issue that I might fix one day).

    Rather than fallback to standard cast syntax (which is 'cast(X, T)'),
    this was tidier.

    I can only guess at what this may mean. Hazarding a guess,
    `pcptr` is a "pointer to a program counter", which is a
    reference type to some type that represents some executable
    memory location in the program. You then have a loop that runs
    until "stopped" is true where you indirect the program counter
    pointer, cast it to a pointer to a function, and then invoke
    the function, right? One presumes you have the, "PC Pointer"
    because it changes over time, otherwise, you'd just give
    whatever it points to a name and call it.

    More generally, I fail to see what this is trying to
    demonstrate. If it's to show some sort of imagined superiority
    over C, I don't see it; that's sort of thing is easy enough to
    write:

    typedef void (*fnptr)(void);

    // Assume uintptr_t *pcptr is declared somewhere.
    do {
    ((fnptr)*pcptr)();
    } while (!stopped);

    E.g.,

    ```
    term% cat b.c
    #include <stdbool.h>
    #include <stddef.h>
    #include <stdint.h>
    #include <stdio.h>

    static void first(void);

    typedef void (*fnptr)(void);
    bool stopped = false;
    uintptr_t pc = (uintptr_t)first;
    uintptr_t *pcptr = &pc;

    void
    done(void)
    {
    printf("done\n");
    stopped = true;
    }

    void
    second(void)
    {
    printf("second\n");
    *pcptr = (uintptr_t)done;
    }

    void
    first(void)
    {
    printf("first\n");
    *pcptr = (uintptr_t)second;
    }

    void
    run(void)
    {
    do {
    ((fnptr)*pcptr)();
    } while (!stopped);
    }

    int
    main(void)
    {
    run();
    return 0;
    }
    term% gcc-16 -std=c11 -pedantic -o b b.c
    term% ./b
    first
    second
    done
    term%
    ```

    Or just have :

    fnptr pc = first;
    fnptr *pcptr = &pc;

    I don't see a need for "uintptr_t", except so that you have to have
    casts like Bart had.


    BTW what name would be given to such a function pointer type?

    I have no idea what your code is supposed to do,

    It's a table of function pointers! All sharing the same signature.

    That's pretty generic. Is it really that hard to guess? You don't need
    to know what they do, other than at some point they will be called as
    handlertable[i](arg).

    That part is fine.

    What's utterly mystifying is what you are trying to show, if
    anything, by posting it. Is this supposed to prove some kind of
    point? Your code is not _a priori_ easier to understand than
    the equivalent C code; if anything, it is harder to understand
    because of your poorly chosen names.

    - Dan C.

    Rust implementation of Timers, mentioned above<--

    As mentioned above, if I were providing the FreeRTOS timers API
    in an alternative language, I'd write it differently from the
    start. In particular, I'd use an enumeration to describe the
    behavior with respect to repeating, and I'd use a closure to
    obviate the need for the opaque id. Something that isn't easy
    to express in the original API is a type of repeating timer that
    waits for the initial period, and then repeats with some
    different period.

    Something like this:

    ```rust
    pub mod timer {
    use std::sync::atomic::{AtomicBool, Ordering};
    use std::time::Duration;

    /// Errors that may occur when working with timers.
    #[derive(Clone, Copy, Debug)]
    pub enum Error {
    Running,
    CantStop,
    WontStop,
    }

    /// Describes the kind of a timer, as defined by its
    /// periodicity.
    ///
    /// A timer can either be a `OneShot` timer, which fires
    /// once, after its timeout expires, or it may be a Repeating
    /// timer, which will automatically reset after its handler
    /// is run and continue firing at the rate defined by the
    /// initial timeout, or it can be a periodic timer, that
    /// will fire the first time at the initial timeout, and
    /// then repeatedly a potentially different timeout. This
    /// use case can be simulated by a OneShot timer that
    /// creates a repeating Timer, but
    ///
    /// Once started, Repeating and Periodic timers continue
    /// firing until explicitly stopped.
    #[derive(Clone, Copy, Debug)]
    pub enum Kind {
    OneShot,
    Repeating,
    Periodic(Duration),
    }

    /// A named timer, that is handled by the given callback.
    pub struct Timer<'a, F> {
    pub name: &'a str,
    pub kind: Kind,
    pub timeout: Duration,
    callback: F,
    running: AtomicBool,
    // Whatever other innards...
    // ...
    }

    /// A read-only "view" into the timer.
    pub trait TimerView {
    fn name(&self) -> &str;
    fn kind(&self) -> Kind;
    fn timeout(&self) -> Duration;
    }

    impl<'a, F: Fn(&dyn TimerView)> Timer<'a, F> {
    /// Creates a new named timer of the given kind with an
    /// initial timeout. When the timeout expires, it will
    /// automatically invoke the given handler.
    pub fn new(
    name: &'a str,
    timeout: Duration,
    kind: Kind,
    callback: F,
    ) -> Timer<'a, F> {
    let running = AtomicBool::new(false);
    Self {
    name,
    kind,
    callback,
    timeout,
    running,
    }
    }

    /// Starts the timer.
    pub fn start(&self) -> Result<(), Error> {
    if self.running.swap(true, Ordering::AcqRel) {
    return Err(Error::Running);
    }
    self.arm(self.timeout)?;
    Ok(())
    }

    /// Stops the timer.
    ///
    /// Note that this inherently races with the timer firing,
    /// and a timer event that occurs while we are disabling
    /// the timer may still invoke `fired` after this returns.
    ///
    /// Callers are advised to determine definitively that
    /// there are no events pending for this timer before
    /// destroying the `Timer` object.
    pub fn stop(&self) -> Result<(), Error> {
    let was_running = self.running.swap(false, Ordering::AcqRel);
    if !was_running {
    return Err(Error::WontStop);
    }
    self.disarm();
    Ok(())
    }

    // Automatically called when the timeout fires.
    //
    // # Safety
    //
    // Nothing may be mutably borrowing a reference to the
    // Timer object when this is called.
    pub(super) unsafe fn fired(&self) -> Result<(), Error> {
    if !self.running.load(Ordering::Acquire) {
    return Ok(());
    }
    (self.callback)(self);
    match self.kind {
    Kind::OneShot => Ok(()),
    Kind::Repeating => self.arm(self.timeout),
    Kind::Periodic(period) => self.arm(period),
    }
    }

    // Arranges for `self.fired(self)` to be called when
    // the given timeout expires.
    fn arm(&self, timeout: Duration) -> Result<(), Error> {
    // Does whatever one does here to actually arm the
    // timer (e.g., calls a HAL to actually program a
    // physical timer to interrupt after the amount of
    // time specified by `Duration`, for example).
    // ...
    Ok(())
    }

    // Disables an armed timer, so that it does not fire
    // after this returns.
    fn disarm(&self) -> Result<(), Error> {
    // whatever one does here to disarm an active timer
    // ...
    Ok(())
    }
    }

    impl<F> TimerView for Timer<'_, F> {
    fn name(&self) -> &str { self.name }
    fn kind(&self) -> Kind { self.kind }
    fn timeout(&self) -> Duration { self.timeout }
    }
    }
    ```

    One might use this with something like,

    ```
    let value = 42;
    let cb = move |timer: &dyn timer::TimerView| {
    println!(
    "Timer '{}' fired; value is {} and duration was {} ms",
    timer.name(),
    value,
    timer.timeout().as_millis()
    );
    };
    let timeout = std::time::Duration::from_millis(100);
    let timer = timer::Timer::new("timer", timeout, timer::Kind::OneShot, &cb);
    timer.start().expect("Timer started");
    //... at some point the timer fires and prints,
    // 'Timer 'timer1' fired; value is 42 and duration was 100 ms'
    }
    ```

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@[email protected] to comp.lang.c on Wed Oct 21 14:21:33 2026
    From Newsgroup: comp.lang.c

    On 21/10/2026 13:33, bart wrote:
    On 21/10/2026 12:21, David Brown wrote:
    On 21/10/2026 03:04, bart wrote:

    Where does the info come from anyway; does the library export a
    suitable typedef? In that case you might as well use it. But if not,
    info must come from elsewhere.

    Of course it "exports" the typedef - it is in one of the library's
    headers.

    You could have said that in the first place. So it's not really a choice then is it?

    What do you mean?

    There is an API in "dns.h" that uses typedefs such as "ip_addr_t" and "dns_found_callback". /Obviously/ those typedefs are also included in
    the header (or other headers included by "dns.h"). This is not
    something that I should have had to point out.


    Then it makes sense to use what they have provided.


    It always makes sense to use the types provided.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@[email protected] to comp.lang.c on Wed Oct 21 15:10:40 2026
    From Newsgroup: comp.lang.c

    On 21/10/2026 00:43, bart wrote:
    On 20/10/2026 22:44, Dan Cross wrote:
    In article <11b8j17$3btus$[email protected]>, bart  <[email protected]> wrote: >>> On 20/10/2026 20:24, Dan Cross wrote:
    In article <11b7k22$2v8e5$[email protected]>, bart  <[email protected]>
    wrote:

    The point is that the name you chose is meaningless to anyone
    other than you.  What's a PCL?  Phase Control Line?  Printer
    Command Language?  Photon Compressor Loop?

    Within the context of that application then it would be clear. You're
    just being overly hostile.

    Not really.  You are, I presume, posting that code to try and
    make some kind of point about how "readable" it is.  But it's
    not readable unless you already know what it does.

    What it does not relevant. This is simply defining an array of T. But because T happens to be a function pointer, DB insists that an alias
    must be created, and a new name invented.

    I did not "insist" or say that an alias "must" be created. I said
    that's normally what you should do in real code, to make it clear,
    readable and maintainable.

    Note that I wrote (in regard to the "pcl" stuff) :

    """
    I have no idea what your code is supposed to do, so I have no idea what
    names would be good. Presumably you /do/ know what it is for - such as
    what "pcl" means - so /you/ pick good names. Maybe "host_handler_fn" ?
    """

    If "pcl" makes sense in the context of your code, that's fine - use it
    in your names.


    But don't use generic names where specific names impart useful
    information. Don't re-use generic names because of a coincidence in the underlying implementation - use names that make sense where they are used.


    Why? Probably because in C, the syntax for function pointers gets hairy.

    No, this is all because I (and Dan) know how to write good code in a
    clear (to appropriate readers) and maintainable manner. The syntax is irrelevant. We appreciate that you find C's declaration syntax
    confusing and difficult - I think that after the first two or three
    hundred repetitions, it finally sank in. But please stop projecting
    your weaknesses and prejudices onto other people. I do not name
    function pointer types because of C's syntax - I name them because the
    code is better in many ways when the types are named. I would do the
    same in Pascal, Rust, Ada, or any other language, regardless of the syntax.


    On the other hand, the code David posted _is_ readable, because
    it uses the language to encode domain-specific information into
    type names.

    Maybe we should create aliases for function signatures more often then,
    then we can encode that extra info.

    So that instead of, for example:

        void SomeFunc(int x, int y) {printf("%d %d\n", x, y);}

    you do:

        typedef void Take2Ints(int x, int y);

        Take2Ints SomeFunc {printf("%d %d\n", x, y);}


    Maybe we should not. That is not helpful to code clarity. It is a
    pointless generic name (showing that you /still/ do not understand the fundamental matter of giving useful and informative names), and instead
    of /giving/ useful additional information, it /hides/ details at the
    point in the code where they are vital.

    Now, if you had a concept of "Coordinate handler" that was expected to
    receive an x, y pair and do something with them, then it is possible
    that you would have a header file "coordinate_handlers.h" with :

    typedef void Coordinate_Handler_Func(int x, int y);

    and some related function declarations :

    Coordinate_Handler_Func dummy_handler;
    Coordinate_Handler_Func simple_printer;
    Coordinate_Handler_Func fly_to_new_coordinates;

    You are putting the emphasis here on what sort of usage you expect for
    these functions, with the assumption that code using them knows how to
    call them. This could be handy if you have another module that needs to
    build an array or other data structure with these functions - it does
    not care about the implementation details, and uses the function type
    (or a pointer to the function type) without looking at its contents:

    #include "coordinate_handlers.h"

    size_t build_coordinate_handler_array(
    Coordinate_Handler_Func * hs, size_t max_handlers)
    {
    assert(max_handlers >= 3);
    hs[0] = &dummy_handler;
    hs[1] = &simple_printer;
    hs[2] = &fly_to_new_coordinates;

    return 3;
    }

    A caller function might have :

    #include "coordinate_handlers.h"

    void call_handler(size_t handler_no, int x, int y) {
    assert(handler_no < no_of_handlers);

    Coordinate_Handler_Func h * handlers[handler_no];
    h(x, y);
    }


    Handler implementations would be written normally :

    #include "coordinate_handlers.h"

    void simple_printer(int x, int y) {
    printf("%d %d\n, x, y);
    }


    Then later when you decide to go to 3 dimensions, you need to change
    code that calls these handlers, and you need to change the handler implementations (and you'll get compile-time errors until you do), but
    generic "in the middle" code like "build_coordinate_handler_array" is unchanged.

    But if the code also happened to need lots of functions for drawing
    titles at x, y coordinates, it would have :

    typedef void Title_Drawer_Func(int x, int y);

    You would /not/ re-use the same typedef, just because the implementation
    is the same, when the /purpose/ is different.


    If you have a suite of functions sharing the signature, then it might be
    a good idea. But funnily enough, you never see this being done.


    Given that it is not remotely close to valid C, I don't think it is particularly surprising.

    (I don't know if this is legal C; but it works fine with my compiler:

    Your compiler is not a C compiler - it's a compiler for an undefined and undocumented superset of an undefined and undocumented subset of an undocumented version of C. If that's all you need, there's nothing
    wrong with that - but what works or does not work with your compiler is
    no indication of what is or is not "legal" C.


      c:\m>type fred.c
      #include <stdio.h>

      typedef void Take2Ints(int x, int y);

      Take2Ints SomeFunc{printf("%d %d\n", x, y);}

      int main(void) { SomeFunc(10, 20); }

      c:\m>bcc -r -q fred
      10 20

    )

    Yeah, you really just don't get it.
    One of us doesn't get it.

    Exactly. I'm fairly sure you are alone here.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@[email protected] (Dan Cross) to comp.lang.c on Wed Oct 21 13:22:26 2026
    From Newsgroup: comp.lang.c

    In article <11baah2$3te3v$[email protected]>,
    David Brown <[email protected]> wrote:
    On 20/10/2026 21:24, Dan Cross wrote:
    In article <11b7k22$2v8e5$[email protected]>, bart <[email protected]> wrote:
    [snip]
    (There was a LOT of antipathy towards my idea to fix the common case of
    'loop-break' clashing with 'switch-break', BECAUSE it did not fix the
    problem of nested loop-break, which is uncommon, even though that wasn't >>> the aim.)

    Those are two different things. No one disagrees with you that
    "nested break from a switch inside of a loop" is relatively more
    common than other variants.

    Quibble - that is not established to my satisfaction. I am not
    convinced that wanting a nested break for "switch inside loop" is more >common than wanting it for "loop inside loop". So I neither agree nor >disagree with that claim. I don't, however, think it matters much -
    both are situations that turn up sometimes in code, and definitive
    answers are neither possible nor useful.

    Ok, that's fair; I shouldn't say "no one disagrees".

    [snip]
    There are plenty of languages that can do this kind of thing
    that are not C and have syntax and semantics closer to what you
    seem to want. Here's an example in Rust:

    pub trait TimerHandle { ... }

    fn CreateTimer<T>(
    timer_name: &str,
    period: std::time::Duration,
    auto_reload: bool,
    timer_id: T,
    handler: fn(&dyn TimerHandle),
    ) -> Result<Timer<T>, TimerError>

    I didn't know what an `UBaseType_t` is, and while "autoreload"
    sounded pretty intuitive, I wasn't sure about the semantics, so
    I looked it up (the example comes from `FreeRTOS`). In this
    context, it is a boolean saying whether the timer should repeat
    with the given periodicity, or whether it is a one-shot.

    FreeRTOS is written in C90 - a mistake, IMHO - and thus does not use
    bool. Instead, it uses constants pdTRUE and pdFALSE of type
    UBaseType_t. UBaseType_t is a type that is dependent on the target - >usually it is either 16-bit or 32-bit. But of course it doesn't matter
    what the underlying types are - you use the typedef names, and the >documented constants.

    Thanks for the context. Your point that the underlying type
    doesn't matter is salient: it's opaque to the programmer, but
    99% of the time the programmer doesn't need to worry about the
    details.

    The timer_id is opaque to the timer, and it looks like it's used
    to facilitating the handler accessing timer-specific data. In
    C, passing it as a `void *` is used as a way to get a poor-man's
    overloading. But Rust has generics, I just made it generic over
    some type T.

    FreeRTOS uses "void *" to mean "pointer to internal structure that you >shouldn't be messing with". It uses this far too often, and is, IMHO, a >poor design choice. (I also dislike the silly Hungarian naming.) I
    would much preferred if there had been :

    struct Internal_Timer_Struct;
    typedef struct Internal_Timer_Struct * timer_id_t;

    and then the parameter "timer_id_t timer_id". So in a re-write, it
    would not be a generic. (You might choose to use a generic for the
    handler function type, so that handler callbacks could have parameters
    of other types, but not for the timer id.)

    I am using these declarations from FreeRTOS (and LWIP) to demonstrate
    the use of function typedefs in massively popular codebases, not to
    claim FreeRTOS is a paradigm of C code design!

    Oh interesting; in this case, I had assumed it was treated as
    a callback-specific type so one could plumb extra context into
    the handler; the documentation I saw suggested it could be used
    by the handler to disambiguate several timers reusing the same
    handler function.

    For example:

    [snip]

    Note this is decently complex behavior, but it's actually quite
    intuitive from the name and the type.

    You have got a very clear picture here, much of it from the names of the >types. For a Rust programmer, you give a good impression of experience
    with C :-)

    I've been known to dabble.

    The only mistake you made is that programmers working on systems using >FreeRTOS and the like, have a fear and loathing of "malloc", have never >heard of "abort()", and do not join our threads because they all run
    until the power is switched off.

    Ha, fair; that was just a made-up example, based on other thread
    libraries I have used (in C). I didn't mean for it to be
    interpreted strictly in the context of FreeRTOS! :-D

    [snip]

    Or just have :

    fnptr pc = first;
    fnptr *pcptr = &pc;

    I don't see a need for "uintptr_t", except so that you have to have
    casts like Bart had.

    Yes. But I wanted to remain faithful to his original, to show
    that one could write a more-or-less exact transliteration in C
    that was extremely similar to his chosen syntax.

    [Snip a bunch of Rust code; the point of which being that
    bart need not complain about lack of an alternative to C]

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@[email protected] to comp.lang.c on Wed Oct 21 15:28:09 2026
    From Newsgroup: comp.lang.c

    On 21/10/2026 03:23, Keith Thompson wrote:
    David Brown <[email protected]> writes:
    On 19/10/2026 23:27, Janis Papanagnou wrote:
    [...]
      * a b     PN (Polish Notation)

    There is no term "Polish Notation" - except as occasionally used to
    mean /postfix/ as a short form of "Reverse Polish Notation". RPN was
    invented, or at least popularised, by the Polish logician Jan
    Łukasiewicz (I admit to looking that up on Wikipedia!). There is no
    "PN" opposite.

    Yes, there most certainly is, and "* a b" is a good example of it.

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

    Jan Łukasiewicz invented what we now call Polish notation in 1924.
    `+ 3 4` is an example (which yields 7). Lisp syntax is more or
    less Polish notation with added parentheses. (I'm sure the phrase
    "more or less" is doing a lot of work.)

    Reverse Polish Notation, RPN, is very well known because it's
    used by some calculators, particularly those made by HP. It's a
    postfix notation. An example of RPN is `3 4 +` (which also yields 7).

    I've never seen the term "Polish Notation", without "Reverse", used
    to refer to postfix notation. PN is prefix; RPN is postfix.

    I have - it was used as a "short" version of "Reverse Polish Notation".

    I have not, that I recall, seen the term "Polish Notation" used to refer
    to prefix notation until Janis' post.

    But I accept that this is purely based on my experience of when /I/ have
    heard (or not heard) the term. I stand by my assertion that "prefix"
    would have been better in the context, but I was wrong about "Polish
    Notation" not being an established term in its own right.


    I see that Janis already pointed out your error. I'm disappointed
    that your followup did not acknowledge it. (I'm not commenting on the
    rest of what Janis wrote.)


    I had not wanted to dwell on it. (I had started a longer reply to
    Janis, but scrapped it.) I had simply intended to recommend terms that
    had no chance of being misinterpreted, given that some of Janis' terms
    had been.

    But yes, I should have acknowledged that mistake on my part.

    Thus I have learned a new term from Janis, and perhaps he has learned a
    little of the another meaning of "monadic" from my post.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@[email protected] to comp.lang.c on Wed Oct 21 16:40:02 2026
    From Newsgroup: comp.lang.c

    On 21/10/2026 13:29, bart wrote:
    On 21/10/2026 10:20, David Brown wrote:
    On 20/10/2026 22:07, bart wrote:
    On 20/10/2026 16:02, David Brown wrote:
    On 20/10/2026 16:11, bart wrote:

    * A further complication was to allow function pointers within that a >>>>>    declaration list

    To me, the big disadvantage of C's declaration syntax is that it
    lets you declare things of different (but related) types in the same
    declaration.

    Yes, but that doesn't bite so much because it is uncommon.


    Unfortunately not - but it is uncommon to mix objects and function
    declarations, or objects of wildly different real types.

    That's what I meant.

    Ok. It's nice to agree sometimes!


         const int const * const p;
           1         2       3

    const 1 applies to the basetype to its right.
    const 2 applies to the basetype to its left.

    These are redundant - they do the same thing.  (I'd have preferred if
    the ordering rules were strict - allowing only "const int" or "int
    const" - but at least people are usually consistent in their style.)


    (Both also can be in the middle with compound types like 'long long'!)

    const 3 is tricky: I think it applies to the * to its left, since it
    says that the pointer value itself is const. But 'p' has type
    'pointer to', so it could apply to that directly.

    Yes - it is "p" that is const,  not the "*".

    I would disagree. This type can also be written as:

     (const int const * const)

    There is no 'p' to apply to. The type describes a pointer to an integer.
    The first two consts say, redundantly, that the integer value is const.

    The third must then apply to the pointer.

    Yes. But "the pointer" is the thing you are declaring.

    I don't think it is worth belabouring this.



    What about this however:

        int * const *  p;

            1   2   3

    I think here, const 2 applies to * 1, which is to it's left, and
    can't apply to 'p' as that is the other side of the * 3.

    *p is of type "int * const" - thus you can use "*p" to access a
    pointer- to-int, but you can't use *p to change that pointer-to-int.

    But what exactly does this 'const' apply to?

    The type of "*p" - the thing that "p" points to.


    I'm suggesting any 'const' applies either to the base type (the one on
    the left) or to a particular '*'.

    In that case the latter 'const's must apply right-to-left to the
    preceding '*'.

    You can view it that way.

    There is a style known as "east const" that aims to put "const" on the
    right where possible (thus "int const", rather than "const int"), so
    that it always applies to the thing immediately to its left. I have
    never liked the style, but it is arguably more consistent.


    Fair to say that is a complete mess, and it is error prone.

    No, it is not at all fair to say that.  It is fair to say that a
    different way of writing types might make it easier to understand -
    but that's a /long/ way from saying it is "a complete mess".  And you
    can't call it "error prone" unless you know that people regularly use
    such declarations, and often have bugs in their code as a result of
    doing so incorrectly.  I think that is an unrealistic claim.

    If there's any confusion about which const applies to which type
    element, then mistakes can be made.

    Mistakes can always be made. And mistakes can always be found, and
    fixed. The questions are, are mistakes made often, are they made more
    often than they would be with a different syntax, are the mistakes left undiscovered, and are they consequential? I don't think so - so I don't
    see the syntax as "error prone".

    Again, I do not think the C declaration syntax is the nicest or clearest
    to be found, compared to some languages - but I do not think it is
    nearly as bad in practice as some people make out.


    You can write this in C++ :

         // This bit is only needed once
         template <typename T> using ptr = T *;

         // p is a pointer to a const pointer to an int
         ptr<const ptr<int>> p;


    That's LTR syntax.  Sure, it also has < > parentheses, but that's a
    minor point since the ordering of the components is what apparently
    matters so much.

    That it is LTR is now irrelevant because I find that incomprehensible anyway. You've turned a linear chain a nested structure ... oh never
    mind, I don't even want to go there with C++.

    Your LTR form /is/ a nested structure - it's just that with this C++
    format (which I have never seen anyone use in practice), the nesting is explicit.


    Or you can write :

         typedef int * p_int;
         const p_int * p;

    Thus p is a pointer to a "const p_int", where a "p_int" is a pointer
    to an int.

    So, a common pattern with you is to use workarounds so that you
    effectively emulate LTR type patterns. Because they are easier to work
    with and understand.

    I'm offering you an alternative, because /you/ find the normal C syntax confusing. /I/ would not write that, because I don't find the C syntax
    here confusing or difficult to read. And mostly I would not write "int
    * const * p" because I have no idea when such a type might be useful.
    (If I knew, then maybe I would give it a specific name.)


    So you do appreciate how they facilitate things, even though they
    introduce an extra level of indirection and also disseminate the type information across the program.

    I appreciate that you are easily confused and have trouble with C
    syntax. I recommend you do one of two things - stop worrying about
    imaginary types with no meaning, or learn to use typedef so that they
    are not so scary for you.


    But you want to underplay how useful it would be to have natural LTR
    type declarations within a syntax.


    I don't see LTR syntax as making a /significant/ or fundamental
    difference. There will be a narrow range of complex types where the C
    syntax is getting hard to follow, but an LTR syntax is easier, but
    beyond that LTR is equally impenetrable. The issue for complex types is
    not the syntax, it is the complexity of the type - and you handle that
    by breaking things down into manageable sections.

    Let us put some numbers into this. (To be clear - these numbers are
    pulled out of the air, and "real" values will depend on the reader, the context, the details of the real code, real alternative syntax, etc.)
    Let us say that C syntax is comprehensible with up to 4 parts - where a
    "part" is a "const", a "*", "[n]" - in addition to the base type. With
    an LTR syntax, let us say it is comprehensible up to 5 parts. Then
    there is no doubt - the LTR syntax /is/ clearer. But does it actually
    matter, in practice? Most declarations require no more than 3 parts -
    with the great majority clustered at 0 or 1 parts. Who cares if it is difficult to read a type declaration you almost never need? And then if
    you have something really complicated - 6 parts or more - it is equally incomprehensible with LTR and C syntax, and should be handled by divide-and-conquer just like anything complicated in programming.

    This is why I can agree that the C syntax is not optimal, that an LTR
    syntax can be clearer, and yet it does not actually matter and the C
    syntax works fine in practice.


    These are different ways to write the same type, including one that is
    LTR, and the main hinder to understanding remains the same - what is
    the type for?

    If you create a type alias voluntarily (I don't mean structs where
    either a tag or a typedef needs to be created) then yes the name should impart something useful.

    But in my view this is often taken too far. Sometimes you have structs
    where every member has a different user-type. When you look further, you find they are all ints. That is just obfuscation.

    Every good thing can be taken too far - but there are lots of good
    reasons for having multiple typedefs that all coincidentally happen to
    boil down to "int".


    (I would accept enumeration types if the compiler can employ that info
    to improve type safety, but that seems to be limited.)

    I agree that C enumeration types are not as "strong" as I'd like.
    Compiler static analysis can help in many ways, but it would be better
    (for me) if they were strongly typed and scoped.


    I've showed even simple types or trying to use 'const' get becomes
    confusing.

    No, you haven't.

    OK. That is not surprising.

    It would make a HUGE difference:

    Your points below are all true, but IMHO all very minor, and do not
    add up to anything much.

    It would eliminate half the issues with C's type syntax. Probably CDECL wouldn't need to exist. Lots of () disappear. It would make pointers-to- arrays more viable.

    But that's nothing in your view. OK again.

    CDECL has never needed to exist. So few () are needed in declarations
    that it doesn't matter if they are there or not. Pointers to arrays
    work fine if you want to use them, but they are not often used in C - primarily because of the array-to-pointer decay in expressions, not
    because of the declaration syntax or the prefix dereferencing operator.


    Your invented confusion.


    That doesn't matter in practice.

    I don't see that as significant.

    I do agree that the decay of expressions using array types into
    pointer types is a source of error in C code - though I do not think
    it is as bad as you do.

    I didn't say anything about, and that wouldn't be affected.


    Ok.


    But I just don't see pointer-to-array expressions to be common enough
    for the difference you describe to be important.


    If you're passing arrays to a function by-reference then the natural way
    is to a have a pointer to the array. C can do that, but nobody ever does
    so, probably because indexing is then so ugly.

    With my idea, (*A)[i] turns into A*[i], a bit less ugly.

    Predictions are of course speculative, but I could not see that making noticeable difference. C programmers rarely use pointers to arrays
    because they rarely give advantages over pointers to the first element
    of an array, the decay in expressions means it is easy to make mistakes,
    and you often need to make a pointer to the first element anyway.

    If array expressions did not decay to pointer expressions, and array parameters were passed as values, it would be a very different matter.


    (4) For pointers to structs, these are the patterns:

         prefix *    With ->    With postfix *

         (*P).m      P->m       P*.m
         (**P).m     (*P)->m    P**.m
         (***P).m    (**P)->m   P***.m

    Which column looks the tidiest?

    Far and away the most common - by orders of magnitude - are pointers
    to structs.  "p->m" looks fine to me, and I prefer it to "p*.m".

    But where's the consistency? Sometimes "." is used for member selection,
    and sometimes "->". And with two pointer levels, you need both!

    The consistency is that you almost always have a pointer to a struct, so
    you can consistently use p->m. There is no need to change that for consistency with a much rarer usage. And of course "." is used for
    member selection when you have a struct object, or when you have already dereferenced a pointer to a struct.


    (6) Your 'int * a, b' example would become:

       int a *, b;

    Much easier, even with that space, to see that '*' does not belong to
    the base type but is a modifier for that variable.

    It's still bad.  I don't think finding a way to make it easier to
    write bad code is a good idea.

    It wouldn't stay bad for long! Because if the intention was to declare
    two pointers, then it's easier to see that this is wrong.

    It is bad (according to my personal style preferences) if your
    intentionally declare an int and a pointer to an int in the same line.
    I am not talking about mistakes here - a mixup between an int and an
    int* will almost certainly result in a compilation failure and the code
    will quickly be fixed to give valid C code.

    C lets you write "int *a, b;" - it is legal C. There are lots of things
    you can write in C that I think are bad code, even though they may be intentional and work as intended. (And even though others will,
    naturally, have different opinions.)

    I would be against any change to C syntax that made it /easier/ for
    people to write such declarations - whether intentional or by mistake.


    So basically, the suggestion would change some very minor things -
    mostly in subjective ways - and not actually do anything for aspects
    of the language where there is more of a consensus that C is sub-
    optimal. And for this, you would want a fundamental change to one of
    the most used operators in all C code!

    Obviously you can't change prefix * now. A postfix /alternative/, in addition to prefix *, could have been introduced decades ago. So by the
    time /you/ encountered C, you might have been using the latter.


    I first used C on a very small scale in the late 1980's, so that was
    quite a few decades ago.

    I expect that a postfix dereferencing operator would have worked fine
    instead of a prefix one - it works fine in Pascal. I don't think it
    would have been "better" in any significant way. Two separate
    dereferencing operators with no difference except the prefix vs. postfix positioning would have been a very bad idea, no matter when it were
    introduced - it would have been a totally unnecessary complication, just adding confusion and inconsistency.

    But even if you were right here, it is no more realistic to go back 4
    decades to add this new postfix dereferencing operator as it is to go
    back 5 decades and pick that one in the first place.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Wed Oct 21 15:41:16 2026
    From Newsgroup: comp.lang.c

    On 21/10/2026 12:21, David Brown wrote:
    On 21/10/2026 03:04, bart wrote:

    Here, one problem is that there are 3 types that I don't know and
    would have to look up.

    Incorrect.

    If I wanted to use function from a language that is not C and for which
    nobody has yet created a set of bindings, then I would have to
    investigate every single abstract type.

    Even then, I might find that a year later, 'err_t' has been defined to
    be something slightly different. Standard types are easier to deal with
    and more likely to be stable.

    That signed char return is unusual; why not 'int'? (How would you even
    print an 'err_t' value anyway)?

    It seems that yet again, you need an explanation of fundamental points
    of software development.  Today's lesson is on "abstraction".

    OK. I've just looked at several graphics libraries. Those have chosen to
    use predominantly standard C types for function return values. And
    standard C types for numeric arguments.

    Sometimes they might be prefixed, eg. GL_int, SDL_bool, probably as abstraction from the vagaries of standard C.

    It seems a trend to invent pointless extra types for everything. In C
    itself, there are about 35 denotations for integer types, and that's
    before you get into clock_t, time_t, offset_t and everything else.

    In general most boil down to one of i32 u32 i64 u64.

    So you can go over the top with abstraction.

    Maybe on some targets (of this portable library), err_t is "signed
    char".

    Why not define it on top of 'int'? Is it likely that large numbers of
    error codes are going to be stored within structs and arrays so that the
    size must be minimal?

    It is also nice to know that it can be used in a switch, and cast to an
    int for printf.

    How would you know that? I thought it was abstract! Maybe err_t is a
    small struct.


    Or look at the "ip_addr_t" type.  It happens, at the moment, to be a struct.  But it might have been a union.  The size and contents of the struct depend on details of how the library is built - whether it has support for ipv4, ipv6, or both.  Maybe a future version will also
    support ipv8, or ipv5 (I've heard some people are trying to make an IP protocol that covers more than IPv4, but without most of the
    complicating additional features of IPv6).  It is an abstract type - you use it without knowing the details.

    I haven't said much about that. It is a struct so some username is
    needed. I renamed it to IP_addr in my example.

    But I'm not sure it needs the _t suffix. (Is it a thing now for every
    typedef name to need _t?)

    I notice however that the argument is a pointer: if ip_addr_t* values
    are commonly passed around, I would put an abstraction around that.

    (However that's partly because how my language works is different; to
    access a member of the struct, I don't need to know if the type of X is
    an actual struct or is a pointer to one; I write X.addr in both cases.)


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Blaine@[email protected] to comp.lang.c on Wed Oct 21 09:29:24 2026
    From Newsgroup: comp.lang.c

    fir wrote:
    Lawrence D’Oliveiro pisze:
    t to end each case-sequence in a switch statement with
    a break-statement: put the break at the same indentation level as the
    case-clause as well as the switch-expression. That way, you can scan
    your eye down a single line f

    some time ago i was saying what the proper switch should like
    (imo, but im not sure if my conclusions are anough to take is a s proven)

    case {} case {}  case {} otherwise {}

    its indeed sorta needed becouse case in fact are ifs
    (not if-elses)  (so some in fact could write

    if {} if {} if {} otherwise {}

    its the same)

     the problem is you  got no group alse
    and here this otherwise need to check all ifs
    "or" them and use group else for them

    this could be written in few ways, but my case case case otherwise names it could also do


    if {} or if {} or if {} else {}

    so either you need logic operators here or predefined constructs like otherwise (maybe both)

    and that should be included not switch wchich is bad imo


    other way is to define distionary more as data construct

    dict {
    'mental'  {/* 1 */}
    'reductionists' {/* 2 */}
    'suck' {/* 3 */}
    }

    then you could use

    dict('reductionists')

    to yeld to  /* 2 */

    this second one parallels to switch keyword


    so c switch mixes them both in bad way..they should be spitet and
    upbuild as showed ;c

    thats my conclusion as switch topic as far by now ;c

    Just start using the switch statement. It's useful in very very very
    many cases. You'll get the hang of it right away. Next, it doesn't just
    test variable type 'int', also notably 'char', among others.
    --
    Can you strip away so we may start again?
    "There’s a switch and they don't
    seem authentic or themselves. It
    feels like I’m an unnecessary
    body and it’s a waste of time to
    even be there." -- Grim, playful Blaine.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@[email protected] to comp.lang.c on Wed Oct 21 17:29:32 2026
    From Newsgroup: comp.lang.c

    On 21/10/2026 15:22, Dan Cross wrote:
    In article <11baah2$3te3v$[email protected]>,
    David Brown <[email protected]> wrote:
    On 20/10/2026 21:24, Dan Cross wrote:
    In article <11b7k22$2v8e5$[email protected]>, bart <[email protected]> wrote: >>>> [snip]
    (There was a LOT of antipathy towards my idea to fix the common case of >>>> 'loop-break' clashing with 'switch-break', BECAUSE it did not fix the
    problem of nested loop-break, which is uncommon, even though that wasn't >>>> the aim.)

    Those are two different things. No one disagrees with you that
    "nested break from a switch inside of a loop" is relatively more
    common than other variants.

    Quibble - that is not established to my satisfaction. I am not
    convinced that wanting a nested break for "switch inside loop" is more
    common than wanting it for "loop inside loop". So I neither agree nor
    disagree with that claim. I don't, however, think it matters much -
    both are situations that turn up sometimes in code, and definitive
    answers are neither possible nor useful.

    Ok, that's fair; I shouldn't say "no one disagrees".

    And I didn't say I /did/ disagree - merely that I don't feel I have the information to disagree or agree.

    We all over-generalise, and that's always bad!


    [snip]
    There are plenty of languages that can do this kind of thing
    that are not C and have syntax and semantics closer to what you
    seem to want. Here's an example in Rust:

    pub trait TimerHandle { ... }

    fn CreateTimer<T>(
    timer_name: &str,
    period: std::time::Duration,
    auto_reload: bool,
    timer_id: T,
    handler: fn(&dyn TimerHandle),
    ) -> Result<Timer<T>, TimerError>

    I didn't know what an `UBaseType_t` is, and while "autoreload"
    sounded pretty intuitive, I wasn't sure about the semantics, so
    I looked it up (the example comes from `FreeRTOS`). In this
    context, it is a boolean saying whether the timer should repeat
    with the given periodicity, or whether it is a one-shot.

    FreeRTOS is written in C90 - a mistake, IMHO - and thus does not use
    bool. Instead, it uses constants pdTRUE and pdFALSE of type
    UBaseType_t. UBaseType_t is a type that is dependent on the target -
    usually it is either 16-bit or 32-bit. But of course it doesn't matter
    what the underlying types are - you use the typedef names, and the
    documented constants.

    Thanks for the context. Your point that the underlying type
    doesn't matter is salient: it's opaque to the programmer, but
    99% of the time the programmer doesn't need to worry about the
    details.

    Yes.


    The timer_id is opaque to the timer, and it looks like it's used
    to facilitating the handler accessing timer-specific data. In
    C, passing it as a `void *` is used as a way to get a poor-man's
    overloading. But Rust has generics, I just made it generic over
    some type T.

    FreeRTOS uses "void *" to mean "pointer to internal structure that you
    shouldn't be messing with". It uses this far too often, and is, IMHO, a
    poor design choice. (I also dislike the silly Hungarian naming.) I
    would much preferred if there had been :

    struct Internal_Timer_Struct;
    typedef struct Internal_Timer_Struct * timer_id_t;

    and then the parameter "timer_id_t timer_id". So in a re-write, it
    would not be a generic. (You might choose to use a generic for the
    handler function type, so that handler callbacks could have parameters
    of other types, but not for the timer id.)

    I am using these declarations from FreeRTOS (and LWIP) to demonstrate
    the use of function typedefs in massively popular codebases, not to
    claim FreeRTOS is a paradigm of C code design!

    Oh interesting; in this case, I had assumed it was treated as
    a callback-specific type so one could plumb extra context into
    the handler; the documentation I saw suggested it could be used
    by the handler to disambiguate several timers reusing the same
    handler function.

    Actually, I have mixed these up, and you are correct - the void* id is user-assigned, and you use it as you wish. There are other places in
    FreeRTOS where pointer types get "erased" and reduced to void*
    unnecessarily, but this was not one of them. (In my poor defence, the FreeRTOS code I have doesn't use timers, and the bits it does use -
    threads and queues, mainly - is abstracted to a C++ interface.)


    For example:

    [snip]

    Note this is decently complex behavior, but it's actually quite
    intuitive from the name and the type.

    You have got a very clear picture here, much of it from the names of the
    types. For a Rust programmer, you give a good impression of experience
    with C :-)

    I've been known to dabble.

    The only mistake you made is that programmers working on systems using
    FreeRTOS and the like, have a fear and loathing of "malloc", have never
    heard of "abort()", and do not join our threads because they all run
    until the power is switched off.

    Ha, fair; that was just a made-up example, based on other thread
    libraries I have used (in C). I didn't mean for it to be
    interpreted strictly in the context of FreeRTOS! :-D

    [snip]

    Or just have :

    fnptr pc = first;
    fnptr *pcptr = &pc;

    I don't see a need for "uintptr_t", except so that you have to have
    casts like Bart had.

    Yes. But I wanted to remain faithful to his original, to show
    that one could write a more-or-less exact transliteration in C
    that was extremely similar to his chosen syntax.

    [Snip a bunch of Rust code; the point of which being that
    bart need not complain about lack of an alternative to C]


    It was interesting to see the Rust code, but it made one thing clear to
    me - Rust should be used for writing Rust code, and not for writing C
    code in Rust syntax.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@[email protected] to comp.lang.c on Wed Oct 21 17:36:26 2026
    From Newsgroup: comp.lang.c

    On 21/10/2026 16:41, bart wrote:
    On 21/10/2026 12:21, David Brown wrote:
    On 21/10/2026 03:04, bart wrote:

    Here, one problem is that there are 3 types that I don't know and
    would have to look up.

    Incorrect.

    If I wanted to use function from a language that is not C and for which nobody has yet created a set of bindings, then I would have to
    investigate every single abstract type.

    So for a one-in-a-million use-cases, you would have to look up the type,
    such as by holding your mouse over the type, or pressing the "navigate
    to definition" shortcut in your IDE. I think it is better to optimise
    for the 999,999 other cases.

    Or you could use a real programming language, for which there is
    probably SWIG support.


    Even then, I might find that a year later, 'err_t' has been defined to
    be something slightly different. Standard types are easier to deal with
    and more likely to be stable.

    Libraries change types for good reasons. Support for one person using
    an obscure language who does not want to have to look up a typedef is
    not going to influence that decision. The world does not revolve around
    you and your unique needs and wants.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@[email protected] (Dan Cross) to comp.lang.c on Wed Oct 21 15:37:11 2026
    From Newsgroup: comp.lang.c

    In article <11baiuc$11ac$[email protected]>, bart <[email protected]> wrote:
    On 21/10/2026 12:21, David Brown wrote:
    On 21/10/2026 03:04, bart wrote:
    Here, one problem is that there are 3 types that I don't know and
    would have to look up.

    Incorrect.

    If I wanted to use function from a language that is not C and for which >nobody has yet created a set of bindings, then I would have to
    investigate every single abstract type.

    That is true of every programming language.

    Even then, I might find that a year later, 'err_t' has been defined to
    be something slightly different. Standard types are easier to deal with
    and more likely to be stable.

    That is also true of every programming language.

    You can write some library in BartM or whatever language you
    like, and someone might write a binding to call it from, say,
    Pascal; and then a year down the road, you might change your
    compiler (since I gather you don't bother with a well-defined
    ABI, based on your not seeming to understand them) or change
    the type of something in a record, and you don't tell the Pascal
    person; now, they've got a program that will probably link
    against your library, and may even work correctly _most of the
    time_, but sometimes will just mysteriously crash.

    Welcome to programming. It's Hard(TM).

    Your answer to that appears to be to simply give up on
    abstraction; others work around it by writing tools (cf, `swig`
    or `bindgen` for Rust).

    That signed char return is unusual; why not 'int'? (How would you even
    print an 'err_t' value anyway)?

    It seems that yet again, you need an explanation of fundamental points
    of software development.  Today's lesson is on "abstraction".

    OK. I've just looked at several graphics libraries. Those have chosen to
    use predominantly standard C types for function return values. And
    standard C types for numeric arguments.

    Sometimes they might be prefixed, eg. GL_int, SDL_bool, probably as >abstraction from the vagaries of standard C.

    It seems a trend to invent pointless extra types for everything. In C >itself, there are about 35 denotations for integer types, and that's
    before you get into clock_t, time_t, offset_t and everything else.

    In general most boil down to one of i32 u32 i64 u64.

    Judicious use of types can render entire categories of errors
    unexpressible. Alexis King wrote a wonderful post about this,
    expressed using Haskell, but the general principles apply more
    broadly.

    https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/

    So you can go over the top with abstraction.

    Of course. Part of becoming a true software engineer is
    learning to find balance between too much abstraction and too
    little.

    Maybe on some targets (of this portable library), err_t is "signed
    char".

    Why not define it on top of 'int'? Is it likely that large numbers of
    error codes are going to be stored within structs and arrays so that the >size must be minimal?

    Because maybe on some platforms it's more efficient to keep it
    in a `signed char`. Who knows? The point is you almost never
    need to care.

    It is also nice to know that it can be used in a switch, and cast to an
    int for printf.

    How would you know that? I thought it was abstract! Maybe err_t is a
    small struct.

    Because the documentation about it tells you that you can: "The
    type `err_t` is used to represent errors. It can be cast to
    `int`." Really, this is table-stakes software development.

    Or look at the "ip_addr_t" type.  It happens, at the moment, to be a
    struct.  But it might have been a union.  The size and contents of the
    struct depend on details of how the library is built - whether it has
    support for ipv4, ipv6, or both.  Maybe a future version will also
    support ipv8, or ipv5 (I've heard some people are trying to make an IP
    protocol that covers more than IPv4, but without most of the
    complicating additional features of IPv6).  It is an abstract type - you >> use it without knowing the details.

    I haven't said much about that. It is a struct so some username is
    needed. I renamed it to IP_addr in my example.

    Huh? Username?

    But I'm not sure it needs the _t suffix. (Is it a thing now for every >typedef name to need _t?)

    I notice however that the argument is a pointer: if ip_addr_t* values
    are commonly passed around, I would put an abstraction around that.

    (However that's partly because how my language works is different; to
    access a member of the struct, I don't need to know if the type of X is
    an actual struct or is a pointer to one; I write X.addr in both cases.)

    So does Rust. You're welcome.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Wed Oct 21 17:22:57 2026
    From Newsgroup: comp.lang.c

    On 21/10/2026 16:37, Dan Cross wrote:
    In article <11baiuc$11ac$[email protected]>, bart <[email protected]> wrote:
    On 21/10/2026 12:21, David Brown wrote:
    On 21/10/2026 03:04, bart wrote:
    Here, one problem is that there are 3 types that I don't know and
    would have to look up.

    Incorrect.

    If I wanted to use function from a language that is not C and for which
    nobody has yet created a set of bindings, then I would have to
    investigate every single abstract type.

    That is true of every programming language.

    It's not clear what you mean by 'that'.

    But typically APIs are primarily expressed as C headers. With mainstream languages, somebody else has usually already done that work.


    Even then, I might find that a year later, 'err_t' has been defined to
    be something slightly different. Standard types are easier to deal with
    and more likely to be stable.

    That is also true of every programming language.

    Then it is also true that standard types will be more stable.

    You can write some library in BartM or whatever language you
    like, and someone might write a binding to call it from, say,
    Pascal; and then a year down the road, you might change your
    compiler (since I gather you don't bother with a well-defined
    ABI, based on your not seeming to understand them

    You still don't get what an ABI is.

    Welcome to programming. It's Hard(TM).

    Some things could be easier. Someone produces library (eg. DLL binary).

    That library exports a set of function names, but not a set of language-neutral function signatures. (And it will not export types,
    structs, enums etc needed to use the library.)

    Why not do that? Just a DLL having the C header API embedded within it
    would be a start! You don't need to source them separately, and they
    will always match in version.

    In general most boil down to one of i32 u32 i64 u64.

    Judicious use of types can render entire categories of errors
    unexpressible. Alexis King wrote a wonderful post about this,
    expressed using Haskell, but the general principles apply more
    broadly.

    If you want to use lots of abstraction then use a language with strict
    type systems that can back them up. Ada for example.

    But it's not a language I'd want to use. You can go too far down that
    path (look at the Frink programming language).


    It is also nice to know that it can be used in a switch, and cast to an
    int for printf.

    How would you know that? I thought it was abstract! Maybe err_t is a
    small struct.

    Because the documentation about it tells you that you can: "The
    type `err_t` is used to represent errors. It can be cast to
    `int`." Really, this is table-stakes software development.

    In this case it doesn't. It is an alias for 's8_t', which is itself an
    alias for 'int8_t' (which itself is probably an alias for 'signed char'
    within 'stdint.h'.

    What it does say however is that, if you define a certain macro, you can
    make err_t' any type you like. I don't know how that would work here; I
    assume it still has to be a numeric type, but it is not stated.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From scott@[email protected] (Scott Lurndal) to comp.lang.c on Wed Oct 21 17:21:10 2026
    From Newsgroup: comp.lang.c

    bart <[email protected]> writes:
    On 21/10/2026 16:37, Dan Cross wrote:

    You can write some library in BartM or whatever language you
    like, and someone might write a binding to call it from, say,
    Pascal; and then a year down the road, you might change your
    compiler (since I gather you don't bother with a well-defined
    ABI, based on your not seeming to understand

    You still don't get what an ABI is.

    Please, enlighten us. Be specific. What exactly
    does the term ABI mean to you?
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Wed Oct 21 19:04:16 2026
    From Newsgroup: comp.lang.c

    On 21/10/2026 18:21, Scott Lurndal wrote:
    bart <[email protected]> writes:
    On 21/10/2026 16:37, Dan Cross wrote:

    You can write some library in BartM or whatever language you
    like, and someone might write a binding to call it from, say,
    Pascal; and then a year down the road, you might change your
    compiler (since I gather you don't bother with a well-defined
    ABI, based on your not seeming to understand

    You still don't get what an ABI is.

    Please, enlighten us. Be specific. What exactly
    does the term ABI mean to you?

    It's what I have to deal with in a compiler back-end if I want to
    support an FFI in a language.

    It's not the same problem as using that FFI to write a set of bindings corresponding with a particular API.

    The latter problem needs to be solved even if there was no back-end and
    no ABI to deal with (eg. transpiling to another language, or lowering to
    some VM).

    I don't why I'm bothering, since somebody will find another stick to
    beat me over the head with or to somehow try to catch me out, but here
    is an example of a function inside MSVCRT.DLL..

    In the C API (ie. stdio.h) it will be expressed like this:

    int puts(const char*);

    In my FFI and in my syntax, it is expressed like this:

    func puts (ichar)i32

    So, this is 'creating a binding'. This can be done manually for this
    one-off example. It's not perfect: on my platform, the C parameter has
    'ref i8' type, but mine is more like 'ref u8'.

    At this point, the ABI doesn't come into it.

    That becomes relevant within the backend for a particular target and
    platform.

    So for this call:

    puts(s)

    the ABI for x64 running Windows will tell me that 's' must be passed in
    rcx, the stack needs a shadow space, it needs to be 16-byte aligned, and
    the 32-bit result is placed in eax.

    For ARM64 running Linux (SYS V), then 's' is passed in x0, and the
    result placed in w0. The stack will always properly aligned.

    The only overlap in API/ABI may be to do with details of how structs may
    be laid out in memory. But generally, C APIs will just follow the C
    rules; I don't consider it an ABI thing. It would be something to deal
    with even if no ABI existed and no native code was generated.

    For my purposes, ABI is about calling conventions. ABI references may
    cover a lot more (eg. for SYS V which likes to make everything as
    complicated as possible).

    So, now tell me what I've got wrong.



    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@[email protected] (Dan Cross) to comp.lang.c on Wed Oct 21 18:38:47 2026
    From Newsgroup: comp.lang.c

    In article <11baur1$63id$[email protected]>, bart <[email protected]> wrote:
    On 21/10/2026 18:21, Scott Lurndal wrote:
    bart <[email protected]> writes:
    On 21/10/2026 16:37, Dan Cross wrote:

    You can write some library in BartM or whatever language you
    like, and someone might write a binding to call it from, say,
    Pascal; and then a year down the road, you might change your
    compiler (since I gather you don't bother with a well-defined
    ABI, based on your not seeming to understand

    You still don't get what an ABI is.

    Please, enlighten us. Be specific. What exactly
    does the term ABI mean to you?

    It's what I have to deal with in a compiler back-end if I want to
    support an FFI in a language.

    It's not the same problem as using that FFI to write a set of bindings >corresponding with a particular API.

    The latter problem needs to be solved even if there was no back-end and
    no ABI to deal with (eg. transpiling to another language, or lowering to >some VM).

    I don't why I'm bothering, since somebody will find another stick to
    beat me over the head with or to somehow try to catch me out, but here
    is an example of a function inside MSVCRT.DLL..

    In the C API (ie. stdio.h) it will be expressed like this:

    int puts(const char*);

    In my FFI and in my syntax, it is expressed like this:

    func puts (ichar)i32

    So, this is 'creating a binding'. This can be done manually for this
    one-off example. It's not perfect: on my platform, the C parameter has
    'ref i8' type, but mine is more like 'ref u8'.

    At this point, the ABI doesn't come into it.

    That becomes relevant within the backend for a particular target and >platform.

    So for this call:

    puts(s)

    the ABI for x64 running Windows will tell me that 's' must be passed in
    rcx, the stack needs a shadow space, it needs to be 16-byte aligned, and
    the 32-bit result is placed in eax.

    For ARM64 running Linux (SYS V), then 's' is passed in x0, and the
    result placed in w0. The stack will always properly aligned.

    The only overlap in API/ABI may be to do with details of how structs may
    be laid out in memory. But generally, C APIs will just follow the C
    rules; I don't consider it an ABI thing. It would be something to deal
    with even if no ABI existed and no native code was generated.

    For my purposes, ABI is about calling conventions. ABI references may
    cover a lot more (eg. for SYS V which likes to make everything as >complicated as possible).

    So, now tell me what I've got wrong.

    Wow. You really, truly, have no idea how any of this works. I
    don't even know where to begin. You just throw around words but
    have no idea what they mean in context.

    It's breathtaking, really.

    - Dan C.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@[email protected] (Dan Cross) to comp.lang.c on Wed Oct 21 18:43:54 2026
    From Newsgroup: comp.lang.c

    In article <11balos$1042$[email protected]>,
    David Brown <[email protected]> wrote:
    On 21/10/2026 15:22, Dan Cross wrote:
    [snip]
    Actually, I have mixed these up, and you are correct - the void* id is >user-assigned, and you use it as you wish. There are other places in >FreeRTOS where pointer types get "erased" and reduced to void* >unnecessarily, but this was not one of them. (In my poor defence, the >FreeRTOS code I have doesn't use timers, and the bits it does use -
    threads and queues, mainly - is abstracted to a C++ interface.)

    No problem!

    It was interesting to see the Rust code, but it made one thing clear to
    me - Rust should be used for writing Rust code, and not for writing C
    code in Rust syntax.

    Yes. When we started working with Rust, most of us had a lot of
    experience in C, C++, etc, and we brought a lot of inherited bad
    habits to our Rust code. At one point, a colleague quipped that
    we were writing, "crust: C in Rust syntax!" We all thought that
    was a great play on words, and adopted it in self-deprecating
    terms. Some people get pretty insulted by it, but it was never
    intended that way.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@[email protected] (Dan Cross) to comp.lang.c on Wed Oct 21 18:56:18 2026
    From Newsgroup: comp.lang.c

    In article <11baot1$3j98$[email protected]>, bart <[email protected]> wrote:
    [snip]
    You still don't get what an ABI is.

    This is the only interesting thing in your post, and only
    because it offers a key insight into your screeds: you use terms
    in a way that matches your own sense of what they mean,
    regardless of how they are used in the wider context. This is a
    good example: later, you said that ABIs are _only_ about calling
    conventions. For you, I'm sure that is true; for others who
    work in the field and use the consensus definitions, it is
    uninformed nonsense. No wonder you feel so attacked; what you
    believe you are saying is competely divorced from the way people
    read it.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From scott@[email protected] (Scott Lurndal) to comp.lang.c on Wed Oct 21 19:17:03 2026
    From Newsgroup: comp.lang.c

    bart <[email protected]> writes:
    On 21/10/2026 18:21, Scott Lurndal wrote:
    bart <[email protected]> writes:
    On 21/10/2026 16:37, Dan Cross wrote:

    You can write some library in BartM or whatever language you
    like, and someone might write a binding to call it from, say,
    Pascal; and then a year down the road, you might change your
    compiler (since I gather you don't bother with a well-defined
    ABI, based on your not seeming to understand

    You still don't get what an ABI is.

    Please, enlighten us. Be specific. What exactly
    does the term ABI mean to you?

    It's what I have to deal with in a compiler back-end if I want to
    support an FFI in a language.

    Ah, so you don't know what an ABI is.

    An Application Binary Interface (ABI) is a
    low-level contract in computer science that
    defines how two compiled binary program modules
    interact with each other at the machine-code level.

    <snip discussions of the well known ABI requirements for
    windows x86_64 and linux on ARM64>[*]

    If you want your compiler to leverage existing libraries
    and/or code written in another language, you need to follow
    the platform ABI. It is that simple.

    Whether you like it or not, is completely irrelevent.

    [*] It is worth noting that the Windows x86 64-bit ABI
    requirement for the caller to reserve space for the
    callee to save registers (shadow store) is quite
    unusual in modern ABIs.

    The stack pointer alignment requirement should be obvious.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Wed Oct 21 20:36:17 2026
    From Newsgroup: comp.lang.c

    On 21/10/2026 19:38, Dan Cross wrote:
    In article <11baur1$63id$[email protected]>, bart <[email protected]> wrote:

    So, now tell me what I've got wrong.

    Wow. You really, truly, have no idea how any of this works. I
    don't even know where to begin. You just throw around words but
    have no idea what they mean in context.

    It's breathtaking, really.
    And Wow, your reply is exactly the kind I expected!

    Of course, you're not going to tell me what API means versus ABI, and
    you're not going to answer my question about what I've got wrong.

    Because actually you don't know. This was apparent from things you've
    said in the past.

    I have actually wondered what you're doing here, and this appears to be
    it: being hostile, patronising, condescending and constantly taking the contrary view no matter what.

    In other words, being a troll.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Wed Oct 21 20:49:11 2026
    From Newsgroup: comp.lang.c

    On 21/10/2026 20:17, Scott Lurndal wrote:
    bart <[email protected]> writes:
    On 21/10/2026 18:21, Scott Lurndal wrote:
    bart <[email protected]> writes:
    On 21/10/2026 16:37, Dan Cross wrote:

    You can write some library in BartM or whatever language you
    like, and someone might write a binding to call it from, say,
    Pascal; and then a year down the road, you might change your
    compiler (since I gather you don't bother with a well-defined
    ABI, based on your not seeming to understand

    You still don't get what an ABI is.

    Please, enlighten us. Be specific. What exactly
    does the term ABI mean to you?

    It's what I have to deal with in a compiler back-end if I want to
    support an FFI in a language.

    Ah, so you don't know what an ABI is.

    An Application Binary Interface (ABI) is a
    low-level contract in computer science that
    defines how two compiled binary program modules
    interact with each other at the machine-code level.

    OK. And how is my statement wrong?

    If you want your compiler to leverage existing libraries
    and/or code written in another language, you need to follow
    the platform ABI. It is that simple.

    OK. And what have I said that contradicts that? I said it is something
    taken care of in the back end of my compiler; and it is a solved problem.

    It sends very much like both of you are confused about the difference
    between API and ABI!

    Whether you like it or not, is completely irrelevent.

    Irrelevant to ... what? You're making about as much sense as the other chap.

    I was describing the problems of interfacing to APIs (with a 'P') and
    DC spouted some stuff about ABIs, which was not relevant to those problems.

    So, are you agreeing with me here that API issues and ABI issues are
    separate matters?

    The stack pointer alignment requirement should be obvious.

    Not really: the ABI has to explicitly state it.

    In any case that is not relevant to the issues I was describing in
    working with APIs.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Chris M. Thomasson@[email protected] to comp.lang.c on Wed Oct 21 13:02:37 2026
    From Newsgroup: comp.lang.c

    On 10/21/2026 5:17 AM, David Brown wrote:
    [...]

    *_t intrudes into POSIX.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@[email protected] (Dan Cross) to comp.lang.c on Wed Oct 21 20:36:04 2026
    From Newsgroup: comp.lang.c

    In article <11bb47i$889c$[email protected]>, bart <[email protected]> wrote:
    On 21/10/2026 19:38, Dan Cross wrote:
    In article <11baur1$63id$[email protected]>, bart <[email protected]> wrote:

    So, now tell me what I've got wrong.

    Wow. You really, truly, have no idea how any of this works. I
    don't even know where to begin. You just throw around words but
    have no idea what they mean in context.

    It's breathtaking, really.

    And Wow, your reply is exactly the kind I expected!

    Of course, you're not going to tell me what API means versus ABI, and
    you're not going to answer my question about what I've got wrong.

    Honestly? No, I'm not. It's clear that if I tried, you would
    either not understand, or deliberately ignore it so you could
    blindly continue in your self-imposed ignorance.

    Because actually you don't know.

    Umm.....

    This was apparent from things you've said in the past.

    You know, it's one thing to be ignorant yourself. It's quite
    another to project that onto others.

    I have actually wondered what you're doing here, and this appears to be
    it: being hostile, patronising, condescending and constantly taking the >contrary view no matter what.

    In other words, being a troll.

    It's apparent that you really, truly, do not understand why so
    many others seem like they are "having a go" at you. I actually
    feel kind of bad for you.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@[email protected] to comp.lang.c on Wed Oct 21 23:10:28 2026
    From Newsgroup: comp.lang.c

    On 21/10/2026 21:36, Dan Cross wrote:
    In article <11bb47i$889c$[email protected]>, bart <[email protected]> wrote:
    On 21/10/2026 19:38, Dan Cross wrote:
    In article <11baur1$63id$[email protected]>, bart <[email protected]> wrote:

    So, now tell me what I've got wrong.

    Wow. You really, truly, have no idea how any of this works. I
    don't even know where to begin. You just throw around words but
    have no idea what they mean in context.

    It's breathtaking, really.

    And Wow, your reply is exactly the kind I expected!

    Of course, you're not going to tell me what API means versus ABI, and
    you're not going to answer my question about what I've got wrong.

    Honestly? No, I'm not. It's clear that if I tried, you would
    either not understand, or deliberately ignore it so you could
    blindly continue in your self-imposed ignorance.

    Because actually you don't know.

    Umm.....

    This was apparent from things you've said in the past.

    You know, it's one thing to be ignorant yourself. It's quite
    another to project that onto others.

    I've seen zero evidence that you know anything about the matter. Just
    bluster.



    I have actually wondered what you're doing here, and this appears to be
    it: being hostile, patronising, condescending and constantly taking the
    contrary view no matter what.

    In other words, being a troll.

    It's apparent that you really, truly, do not understand why so
    many others seem like they are "having a go" at you. I actually
    feel kind of bad for you.


    If you don't know this stuff, that would be perfectly fine, not everyone
    is into compilers.

    But refusing to admit that you mixed up API/ABI and instead gaslighting
    others into thinking they're the ones in the wrong is unacceptable and childish.

    I've looked at the 40 or so posts you've made in the last few days, half
    of them were replies to me, all unpleasant exchanges.

    This is just persecution, constantly attacking and belittling at the
    personal level. Maybe you're some sick fuck and and you get a kick out
    of it, then you should get help together with JP, that other wonderful
    person.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@[email protected] (Dan Cross) to comp.lang.c on Wed Oct 21 22:55:42 2026
    From Newsgroup: comp.lang.c

    In article <11bbd8k$bhfq$[email protected]>, bart <[email protected]> wrote:
    On 21/10/2026 21:36, Dan Cross wrote:
    In article <11bb47i$889c$[email protected]>, bart <[email protected]> wrote:
    On 21/10/2026 19:38, Dan Cross wrote:
    In article <11baur1$63id$[email protected]>, bart <[email protected]> wrote: >>>
    So, now tell me what I've got wrong.

    Wow. You really, truly, have no idea how any of this works. I
    don't even know where to begin. You just throw around words but
    have no idea what they mean in context.

    It's breathtaking, really.

    And Wow, your reply is exactly the kind I expected!

    Of course, you're not going to tell me what API means versus ABI, and
    you're not going to answer my question about what I've got wrong.

    Honestly? No, I'm not. It's clear that if I tried, you would
    either not understand, or deliberately ignore it so you could
    blindly continue in your self-imposed ignorance.

    Because actually you don't know.

    Umm.....

    This was apparent from things you've said in the past.

    You know, it's one thing to be ignorant yourself. It's quite
    another to project that onto others.

    I've seen zero evidence that you know anything about the matter. Just >bluster.

    And sadly, I've seen plenty of evidence confirming that you know
    nothing about it at all.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@[email protected] to comp.lang.c on Thu Oct 22 00:33:39 2026
    From Newsgroup: comp.lang.c

    On Wed, 21 Oct 2026 09:29:24 -0600, Blaine wrote:

    Just start using the switch statement. It's useful in very very very
    many cases.

    Has a well-known pitfall, though.

    How not to forget to end each case-sequence in a switch statement with
    a break-statement: put the break at the same indentation level as the case-clause as well as the switch-expression. That way, you can scan
    your eye down a single line for each switch-statement to be sure that
    no breaks are missing. A reasonably-complex example, with a nested
    switch for added interest:

    real stack_calc
    (
    stackcalc_op op,
    ...
    )
    /* starting with an empty operand stack, carries out the specified
    operations on the specified operands, at the end of which there
    should be just a single value on the operand stack. This value is
    popped and returned as the function result. */
    {
    real * opstack = NULL;
    size_t
    opstacklen = 0,
    opstackalloc = 0;
    real result;
    va_list args;
    va_start(args, op);
    bool first = true;
    bool done = false;
    for (;;)
    {
    if (not first)
    {
    op = va_arg(args, stackcalc_op);
    } /*if*/
    first = false;
    switch (op)
    {
    case STACKCALC_END:
    done = true;
    break;
    case STACKCALC_PUSH:
    {
    if (opstacklen == opstackalloc)
    {
    opstackalloc += 16;
    opstack = realloc(opstack, opstackalloc * sizeof(real));
    bugcheck(opstack != NULL, "unable to expand operand stack beyond %d", opstacklen);
    } /*if*/
    opstack[opstacklen] = va_arg(args, real);
    ++opstacklen;
    }
    break;
    case STACKCALC_ADD:
    case STACKCALC_SUB:
    case STACKCALC_MUL:
    case STACKCALC_DIV:
    bugcheck(opstacklen >= 2, "not enough operands for operator %d", op);
    {
    const real op2 = opstack[opstacklen - 1];
    real op1 = opstack[opstacklen - 2];
    switch (op)
    {
    case STACKCALC_ADD:
    op1 += op2;
    break;
    case STACKCALC_SUB:
    op1 -= op2;
    break;
    case STACKCALC_MUL:
    op1 *= op2;
    break;
    case STACKCALC_DIV:
    op1 /= op2;
    break;
    } /*switch*/
    --opstacklen;
    opstack[opstacklen - 1] = op1;
    }
    break;
    default:
    bugcheck(false, "invalid operator %d", op);
    break;
    } /*switch*/
    if (done)
    break;
    } /*for*/
    va_end(args);
    bugcheck(opstacklen == 1, "expecting exactly one result left on stack");
    result = opstack[0];
    free(opstack);
    return result;
    } /*stack_calc*/
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@[email protected] to comp.lang.c on Thu Oct 22 08:57:28 2026
    From Newsgroup: comp.lang.c

    On 21/10/2026 22:02, Chris M. Thomasson wrote:
    On 10/21/2026 5:17 AM, David Brown wrote:
    [...]

    *_t intrudes into POSIX.

    I don't program for POSIX, so I don't care. The same applies to most
    code that is used in connection with FreeRTOS, or LWIP. (Of course
    there will be some overlap - bits of code that are intended to run on a microcontroller but tested with code running native on a PC.)

    I don't know if the "_t" convention for type identifiers started with
    POSIX, but it has certainly far outgrown POSIX. And I think the smart
    folks behind POSIX know this, and will not assume that just because they
    pick a new type name ending in _t, it will not conflict with some user
    code. As C doesn't have namespaces, there is always a risk of
    conflicting names - you just have to try to avoid clashes in things you
    are likely to see.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From fir@[email protected] to comp.lang.c on Thu Oct 22 09:51:13 2026
    From Newsgroup: comp.lang.c

    Blaine pisze:
    fir wrote:
    Lawrence D’Oliveiro pisze:
    t to end each case-sequence in a switch statement with
    a break-statement: put the break at the same indentation level as the
    case-clause as well as the switch-expression. That way, you can scan
    your eye down a single line f

    some time ago i was saying what the proper switch should like
    (imo, but im not sure if my conclusions are anough to take is a s proven)

    case {} case {}  case {} otherwise {}

    its indeed sorta needed becouse case in fact are ifs
    (not if-elses)  (so some in fact could write

    if {} if {} if {} otherwise {}

    its the same)

      the problem is you  got no group alse
    and here this otherwise need to check all ifs
    "or" them and use group else for them

    this could be written in few ways, but my case case case otherwise
    names it
    could also do


    if {} or if {} or if {} else {}

    so either you need logic operators here or predefined constructs like
    otherwise (maybe both)

    and that should be included not switch wchich is bad imo


    other way is to define distionary more as data construct

    dict {
    'mental'  {/* 1 */}
    'reductionists' {/* 2 */}
    'suck' {/* 3 */}
    }

    then you could use

    dict('reductionists')

    to yeld to  /* 2 */

    this second one parallels to switch keyword


    so c switch mixes them both in bad way..they should be spitet and
    upbuild as showed ;c

    thats my conclusion as switch topic as far by now ;c

    Just start using the switch statement. It's useful in very very very
    many cases. You'll get the hang of it right away. Next, it doesn't just
    test variable type 'int', also notably 'char', among others.

    how do you know i dont use it?


    in fact i dont use it its not logical (as roven above) yet looks ugly

    (im not using parts of c quite happily especily switch and macros
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@[email protected] (Dan Cross) to comp.lang.c on Thu Oct 22 12:56:29 2026
    From Newsgroup: comp.lang.c

    In article <11bcc4o$jt81$[email protected]>,
    David Brown <[email protected]> wrote:
    On 21/10/2026 22:02, Chris M. Thomasson wrote:
    On 10/21/2026 5:17 AM, David Brown wrote:
    [...]

    *_t intrudes into POSIX.

    I don't program for POSIX, so I don't care. The same applies to most
    code that is used in connection with FreeRTOS, or LWIP. (Of course
    there will be some overlap - bits of code that are intended to run on a >microcontroller but tested with code running native on a PC.)

    I don't know if the "_t" convention for type identifiers started with
    POSIX, but it has certainly far outgrown POSIX. And I think the smart
    folks behind POSIX know this, and will not assume that just because they >pick a new type name ending in _t, it will not conflict with some user
    code. As C doesn't have namespaces, there is always a risk of
    conflicting names - you just have to try to avoid clashes in things you
    are likely to see.

    It definitely predates POSIX. `typdef` appears to have come
    into the language with "Typesetter C", which first shipped in
    7th Edition research Unix, and 7th Ed had types ending in `_t`;
    so 1979 or thereabouts. For instance, `daddr_t`, `time_t`, and
    `caddr_t` to represent disk block addresses, times, and generic
    addresses, respectively. Curiously, `size_t` isn't there yet,
    and appears to arrive in 3bsd (also 1979, but based on 32/V),
    where it is sized (it's just a typedef for `int`). `size_t`
    makes it back into Research Unix with the 8th Edition, based
    on 4BSD; probably 4.1. It is signed in 8th Ed, and is a typedef
    for `long`. My notes put it into AT&T Unix with System V
    Release 3, where it is unsigned.

    POSIX started in 1984, building on work done by /usr/group, and
    the first issue of POSIX was released in 1988.

    Anyway, the point is that the `_t` convention predates POSIX
    (and ANSI C) by about a decade.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From fir@[email protected] to comp.lang.c on Thu Oct 22 17:19:00 2026
    From Newsgroup: comp.lang.c

    bart pisze:
    On 21/10/2026 21:36, Dan Cross wrote:
    In article <11bb47i$889c$[email protected]>, bart  <[email protected]> wrote:
    On 21/10/2026 19:38, Dan Cross wrote:
    In article <11baur1$63id$[email protected]>, bart  <[email protected]> wrote: >>>
    So, now tell me what I've got wrong.

    Wow.  You really, truly, have no idea how any of this works.  I
    don't even know where to begin.  You just throw around words but
    have no idea what they mean in context.

    It's breathtaking, really.

    And Wow, your reply is exactly the kind I expected!

    Of course, you're not going to tell me what API means versus ABI, and
    you're not going to answer my question about what I've got wrong.

    Honestly?  No, I'm not.  It's clear that if I tried, you would
    either not understand, or deliberately ignore it so you could
    blindly continue in your self-imposed ignorance.

    Because actually you don't know.

    Umm.....

    This was apparent from things you've said in the past.

    You know, it's one thing to be ignorant yourself.  It's quite
    another to project that onto others.

    I've seen zero evidence that you know anything about the matter. Just bluster.



    I have actually wondered what you're doing here, and this appears to be
    it: being hostile, patronising, condescending and constantly taking the
    contrary view no matter what.

    In other words, being a troll.

    It's apparent that you really, truly, do not understand why so
    many others seem like they are "having a go" at you.  I actually
    feel kind of bad for you.


    If you don't know this stuff, that would be perfectly fine, not everyone
    is into compilers.

    But refusing to admit that you mixed up API/ABI and instead gaslighting others into thinking they're the ones in the wrong is unacceptable and childish.

    I've looked at the 40 or so posts you've made in the last few days, half
    of them were replies to me, all unpleasant exchanges.

    This is just persecution, constantly attacking and belittling at the personal level. Maybe you're some sick fuck and and you get a kick out
    of it, then you should get help together with JP, that other wonderful person.


    i dont know as to dan cross (only read some parts of side discusions
    here) but for sure some people here are somewhat trollish - note keith thompson and his sidekicks ;c

    but overally clc is quite decent and even this trolls are standable
    (mostly)..

    maybe its another advantage of writig with mistipes trolls not go into
    you way coz they dont understood what you write ;c

    clc is decent place coz honestly wide world has overally much worse
    level than here imo..especially if some opens co called 'media'..thats terrible thing
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Kaz Kylheku@[email protected] to comp.lang.c on Thu Oct 22 16:54:45 2026
    From Newsgroup: comp.lang.c

    On 2026-10-22, David Brown <[email protected]> wrote:
    On 21/10/2026 22:02, Chris M. Thomasson wrote:
    On 10/21/2026 5:17 AM, David Brown wrote:
    [...]

    *_t intrudes into POSIX.

    I don't program for POSIX, so I don't care. The same applies to most
    code that is used in connection with FreeRTOS, or LWIP. (Of course
    there will be some overlap - bits of code that are intended to run on a microcontroller but tested with code running native on a PC.)

    I don't know if the "_t" convention for type identifiers started with
    POSIX, but it has certainly far outgrown POSIX. And I think the smart
    folks behind POSIX know this, and will not assume that just because they pick a new type name ending in _t, it will not conflict with some user
    code. As C doesn't have namespaces, there is always a risk of
    conflicting names - you just have to try to avoid clashes in things you
    are likely to see.

    These namespace declarations are really just a "heads up". POSIX
    isn't saying, don't have an identifier ending in _t in a namespace
    shared by typedefs. Rather, it is saying that new typedefs appearing
    in POSIX will be in that namespace.

    Consider this argument: whenever POSIX or ISO C introduces a new
    public identifier, it's necessarily going to start with "a", or else if
    not, then with "b", or else with "c", ... or else with "z"
    or perhaps the underscore.

    That doesn't mean you stop using identifiers in programming.

    "nullptr" is now a keyword, previously a valid identifier not in
    any proclaimed reserved namespace. Progrems which used it have
    to be changed to work with the newer language.

    Avoiding proclaimed namespaces will not protect you from clashes;
    only from clashes that would occur in those namespaces.

    Some spaces like _t are too attractive to avoid, because they are tied
    to an important, popular convention that everyone understands,
    and the benefits outweigh the unrealized risk of a future clash.
    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @[email protected]
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Kaz Kylheku@[email protected] to comp.lang.c on Thu Oct 22 17:00:54 2026
    From Newsgroup: comp.lang.c

    On 2026-10-22, Dan Cross <[email protected]> wrote:
    Anyway, the point is that the `_t` convention predates POSIX
    (and ANSI C) by about a decade.

    Speaking of caddr_t, that one was spread outside of Unix. I remember
    caddr_t cropping up when I was working with Microsoft C on DOS in 1990. ANSI/ISO C and its void * were still new, and caddr_t was one of the conventions for a pointer-to-anything.
    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @[email protected]
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@[email protected] to comp.lang.c on Thu Oct 22 21:09:39 2026
    From Newsgroup: comp.lang.c

    On 22/10/2026 18:54, Kaz Kylheku wrote:
    On 2026-10-22, David Brown <[email protected]> wrote:
    On 21/10/2026 22:02, Chris M. Thomasson wrote:
    On 10/21/2026 5:17 AM, David Brown wrote:
    [...]

    *_t intrudes into POSIX.

    I don't program for POSIX, so I don't care. The same applies to most
    code that is used in connection with FreeRTOS, or LWIP. (Of course
    there will be some overlap - bits of code that are intended to run on a
    microcontroller but tested with code running native on a PC.)

    I don't know if the "_t" convention for type identifiers started with
    POSIX, but it has certainly far outgrown POSIX. And I think the smart
    folks behind POSIX know this, and will not assume that just because they
    pick a new type name ending in _t, it will not conflict with some user
    code. As C doesn't have namespaces, there is always a risk of
    conflicting names - you just have to try to avoid clashes in things you
    are likely to see.

    These namespace declarations are really just a "heads up". POSIX
    isn't saying, don't have an identifier ending in _t in a namespace
    shared by typedefs. Rather, it is saying that new typedefs appearing
    in POSIX will be in that namespace.

    Consider this argument: whenever POSIX or ISO C introduces a new
    public identifier, it's necessarily going to start with "a", or else if
    not, then with "b", or else with "c", ... or else with "z"
    or perhaps the underscore.

    That doesn't mean you stop using identifiers in programming.

    "nullptr" is now a keyword, previously a valid identifier not in
    any proclaimed reserved namespace. Progrems which used it have
    to be changed to work with the newer language.

    Avoiding proclaimed namespaces will not protect you from clashes;
    only from clashes that would occur in those namespaces.

    Some spaces like _t are too attractive to avoid, because they are tied
    to an important, popular convention that everyone understands,
    and the benefits outweigh the unrealized risk of a future clash.


    I agree entirely.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Chris M. Thomasson@[email protected] to comp.lang.c on Thu Oct 22 12:46:42 2026
    From Newsgroup: comp.lang.c

    On 10/22/2026 9:54 AM, Kaz Kylheku wrote:
    On 2026-10-22, David Brown <[email protected]> wrote:
    On 21/10/2026 22:02, Chris M. Thomasson wrote:
    On 10/21/2026 5:17 AM, David Brown wrote:
    [...]

    *_t intrudes into POSIX.

    I don't program for POSIX, so I don't care. The same applies to most
    code that is used in connection with FreeRTOS, or LWIP. (Of course
    there will be some overlap - bits of code that are intended to run on a
    microcontroller but tested with code running native on a PC.)

    I don't know if the "_t" convention for type identifiers started with
    POSIX, but it has certainly far outgrown POSIX. And I think the smart
    folks behind POSIX know this, and will not assume that just because they
    pick a new type name ending in _t, it will not conflict with some user
    code. As C doesn't have namespaces, there is always a risk of
    conflicting names - you just have to try to avoid clashes in things you
    are likely to see.

    These namespace declarations are really just a "heads up". POSIX
    isn't saying, don't have an identifier ending in _t in a namespace
    shared by typedefs. Rather, it is saying that new typedefs appearing
    in POSIX will be in that namespace.

    Consider this argument: whenever POSIX or ISO C introduces a new
    public identifier, it's necessarily going to start with "a", or else if
    not, then with "b", or else with "c", ... or else with "z"
    or perhaps the underscore.

    That doesn't mean you stop using identifiers in programming.

    "nullptr" is now a keyword, previously a valid identifier not in
    any proclaimed reserved namespace. Progrems which used it have
    to be changed to work with the newer language.

    Avoiding proclaimed namespaces will not protect you from clashes;
    only from clashes that would occur in those namespaces.

    Some spaces like _t are too attractive to avoid, because they are tied
    to an important, popular convention that everyone understands,
    and the benefits outweigh the unrealized risk of a future clash.


    Touche. How about _this vs this_. I just use self and be done with it.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@[email protected] to comp.lang.c on Thu Oct 22 16:42:50 2026
    From Newsgroup: comp.lang.c

    Kaz Kylheku <[email protected]> writes:
    [...]
    These namespace declarations are really just a "heads up". POSIX
    isn't saying, don't have an identifier ending in _t in a namespace
    shared by typedefs. Rather, it is saying that new typedefs appearing
    in POSIX will be in that namespace.
    [...]

    No, it says that all conforming applications are required to avoid
    symbols ending in "_t".

    https://pubs.opengroup.org/onlinepubs/9799919799/xrat/V4_xsh_chap01.html B.2.11.1 Defined Types

    The requirement that additional types defined in this section
    end in "_t" was prompted by the problem of name space pollution.
    It is difficult to define a type (where that type is not one
    defined by POSIX.1-2024) in one header file and use it in another
    without adding symbols to the name space of the program. To
    allow implementors to provide their own types, all conforming
    applications are required to avoid symbols ending in "_t",
    which permits the implementor to provide additional types.
    Because a major use of types is in the definition of structure
    members, which can (and in many cases must) be added to the
    structures defined in POSIX.1-2024, the need for additional
    types is compelling.

    Of course you don't have to avoid defining symbols ending with "_t"
    if you don't want to, but if you do so you don't have a "conforming application" as far as POSIX is concerned.

    It is, of course, an imperfect solution.
    --
    Keith Thompson (The_Other_Keith) [email protected]
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Blaine@[email protected] to comp.lang.c on Thu Oct 22 18:38:11 2026
    From Newsgroup: comp.lang.c

    Keith Thompson wrote:
    Kaz Kylheku <[email protected]> writes:
    [...]
    These namespace declarations are really just a "heads up". POSIX
    isn't saying, don't have an identifier ending in _t in a namespace
    shared by typedefs. Rather, it is saying that new typedefs appearing
    in POSIX will be in that namespace.
    [...]

    No, it says that all conforming applications are required to avoid
    symbols ending in "_t".

    https://pubs.opengroup.org/onlinepubs/9799919799/xrat/V4_xsh_chap01.html B.2.11.1 Defined Types

    The requirement that additional types defined in this section
    end in "_t" was prompted by the problem of name space pollution.
    It is difficult to define a type (where that type is not one
    defined by POSIX.1-2024) in one header file and use it in another
    without adding symbols to the name space of the program. To
    allow implementors to provide their own types, all conforming
    applications are required to avoid symbols ending in "_t",
    which permits the implementor to provide additional types.
    Because a major use of types is in the definition of structure
    members, which can (and in many cases must) be added to the
    structures defined in POSIX.1-2024, the need for additional
    types is compelling.

    Of course you don't have to avoid defining symbols ending with "_t"
    if you don't want to, but if you do so you don't have a "conforming application" as far as POSIX is concerned.

    It is, of course, an imperfect solution.

    Aside from having to type 'break' for each 'case', do you have a
    legitimate case?
    --
    Can you strip away so we may start again?
    "There’s a switch and they don't
    seem authentic or themselves. It
    feels like I’m an unnecessary
    body and it’s a waste of time to
    even be there." -- Grim, playful Blaine.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Kaz Kylheku@[email protected] to comp.lang.c on Fri Oct 23 04:23:02 2026
    From Newsgroup: comp.lang.c

    On 2026-10-22, Keith Thompson <[email protected]> wrote:
    Kaz Kylheku <[email protected]> writes:
    [...]
    These namespace declarations are really just a "heads up". POSIX
    isn't saying, don't have an identifier ending in _t in a namespace
    shared by typedefs. Rather, it is saying that new typedefs appearing
    in POSIX will be in that namespace.
    [...]

    No, it says that all conforming applications are required to avoid
    symbols ending in "_t".

    That concept is needed in order to make it the application's fault
    when it suddenly fails to build because it's using foo_t, and
    POSIX decides to introduced that into <sys/types.h>.

    If you use _t, a clash may happen, and if it does, then since POSIX told-you-so, it must be your program that is nonconforming, and not the
    POSIX has a defect or the implementation is nonconforming.

    Of course you don't have to avoid defining symbols ending with "_t"
    if you don't want to, but if you do so you don't have a "conforming application" as far as POSIX is concerned.

    This is okay if you have a grip on the nonconformances in the
    application. You know where they are and have a way to be informed when
    they turn into real problems and a plan for that situation.

    Remember, a program that uses nullptr as a variable name was once
    conforming. Through no change in the program whatsoever, it became nonconforming. Playing the conformance game in this area is largely
    a fool's errand.
    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @[email protected]
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@[email protected] to comp.lang.c on Fri Oct 23 09:37:45 2026
    From Newsgroup: comp.lang.c

    On 22/10/2026 21:46, Chris M. Thomasson wrote:
    On 10/22/2026 9:54 AM, Kaz Kylheku wrote:
    On 2026-10-22, David Brown <[email protected]> wrote:
    On 21/10/2026 22:02, Chris M. Thomasson wrote:
    On 10/21/2026 5:17 AM, David Brown wrote:
    [...]

    *_t intrudes into POSIX.

    I don't program for POSIX, so I don't care.  The same applies to most
    code that is used in connection with FreeRTOS, or LWIP.  (Of course
    there will be some overlap - bits of code that are intended to run on a
    microcontroller but tested with code running native on a PC.)


    Avoiding proclaimed namespaces will not protect you from clashes;
    only from clashes that would occur in those namespaces.

    Some spaces like _t are too attractive to avoid, because they are tied
    to an important, popular convention that everyone understands,
    and the benefits outweigh the unrealized risk of a future clash.


    Touche. How about _this vs this_. I just use self and be done with it.

    Imagine, just for a moment, that the rest of us are not privy to the
    jumble of thoughts and ideas that jump around in your head. I don't
    have the context of what you are thinking about. So I have no idea what
    you mean by this.

    Instead of posting random out-of-context snippets of thought, either
    write posts that say what you are talking about, or don't bother. (And
    do /not/ imagine that posting reams of unconnected code is a useful alternative.)

    If you are trying to say something about avoiding C++ keywords when
    picking identifiers in C coding, say that. If you are trying to say
    something about naming conventions for C++ class members, feel free to
    talk about that too - in comp.lang.c++. If you are trying to say
    something else, say it. Or drop it, if you prefer.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@[email protected] to comp.lang.c on Fri Oct 23 01:09:31 2026
    From Newsgroup: comp.lang.c

    Kaz Kylheku <[email protected]> writes:
    On 2026-10-22, Keith Thompson <[email protected]> wrote:
    Kaz Kylheku <[email protected]> writes:
    [...]
    These namespace declarations are really just a "heads up". POSIX
    isn't saying, don't have an identifier ending in _t in a namespace
    shared by typedefs. Rather, it is saying that new typedefs appearing
    in POSIX will be in that namespace.
    [...]

    No, it says that all conforming applications are required to avoid
    symbols ending in "_t".

    That concept is needed in order to make it the application's fault
    when it suddenly fails to build because it's using foo_t, and
    POSIX decides to introduced that into <sys/types.h>.

    If you use _t, a clash may happen, and if it does, then since POSIX told-you-so, it must be your program that is nonconforming, and not the
    POSIX has a defect or the implementation is nonconforming.

    Of course you don't have to avoid defining symbols ending with "_t"
    if you don't want to, but if you do so you don't have a "conforming
    application" as far as POSIX is concerned.

    This is okay if you have a grip on the nonconformances in the
    application. You know where they are and have a way to be informed when
    they turn into real problems and a plan for that situation.

    Remember, a program that uses nullptr as a variable name was once
    conforming. Through no change in the program whatsoever, it became nonconforming. Playing the conformance game in this area is largely
    a fool's errand.

    Yes, I understand all that. I was commenting on what POSIX actually
    says.
    --
    Keith Thompson (The_Other_Keith) [email protected]
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Chris M. Thomasson@[email protected] to comp.lang.c on Fri Oct 23 14:21:15 2026
    From Newsgroup: comp.lang.c

    On 10/23/2026 12:37 AM, David Brown wrote:
    On 22/10/2026 21:46, Chris M. Thomasson wrote:
    On 10/22/2026 9:54 AM, Kaz Kylheku wrote:
    On 2026-10-22, David Brown <[email protected]> wrote:
    On 21/10/2026 22:02, Chris M. Thomasson wrote:
    On 10/21/2026 5:17 AM, David Brown wrote:
    [...]

    *_t intrudes into POSIX.

    I don't program for POSIX, so I don't care.  The same applies to most >>>> code that is used in connection with FreeRTOS, or LWIP.  (Of course
    there will be some overlap - bits of code that are intended to run on a >>>> microcontroller but tested with code running native on a PC.)


    Avoiding proclaimed namespaces will not protect you from clashes;
    only from clashes that would occur in those namespaces.

    Some spaces like _t are too attractive to avoid, because they are tied
    to an important, popular convention that everyone understands,
    and the benefits outweigh the unrealized risk of a future clash.


    Touche. How about _this vs this_. I just use self and be done with it.

    Imagine, just for a moment, that the rest of us are not privy to the
    jumble of thoughts and ideas that jump around in your head.  I don't
    have the context of what you are thinking about.  So I have no idea what you mean by this.

    Instead of posting random out-of-context snippets of thought, either
    write posts that say what you are talking about, or don't bother.  (And
    do /not/ imagine that posting reams of unconnected code is a useful alternative.)

    If you are trying to say something about avoiding C++ keywords when
    picking identifiers in C coding, say that.  If you are trying to say something about naming conventions for C++ class members, feel free to
    talk about that too - in comp.lang.c++.  If you are trying to say
    something else, say it.  Or drop it, if you prefer.


    Or, Well,

    _this

    vs

    this_

    Are they both legal?

    I like self.

    void foo(struct foo* const self);

    vs

    void foo(struct foo* const _this);
    void foo(struct foo* const this);
    void foo(struct foo* const this_);

    ? For some reason I do not want to use this in C.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@[email protected] to comp.lang.c on Fri Oct 23 22:40:08 2026
    From Newsgroup: comp.lang.c

    On Fri, 23 Oct 2026 14:21:15 -0700, Chris M. Thomasson wrote:

    I like self.

    void foo(struct foo* const self);

    The trouble with a fixed name is, how do you refer to the instance of
    an outer class?
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Chris M. Thomasson@[email protected] to comp.lang.c on Fri Oct 23 18:33:56 2026
    From Newsgroup: comp.lang.c

    On 10/23/2026 3:40 PM, Lawrence D’Oliveiro wrote:
    On Fri, 23 Oct 2026 14:21:15 -0700, Chris M. Thomasson wrote:

    I like self.

    void foo(struct foo* const self);

    The trouble with a fixed name is, how do you refer to the instance of
    an outer class?

    Well, self can be internal to the API logic. See, user code does not
    need to care how self is organized. It just needs to allocate n bytes
    aligned on a boundary and call into the API to init it. calling a
    deinit, or destroy whatever after its done. So the caller manages the
    main memory. After its done it can make the memory go out of scope or deallocate it, free or whatever.

    So, internal to the lib, self->foo is there.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@[email protected] to comp.lang.c on Sat Oct 24 12:58:01 2026
    From Newsgroup: comp.lang.c

    On 23/10/2026 23:21, Chris M. Thomasson wrote:
    On 10/23/2026 12:37 AM, David Brown wrote:
    On 22/10/2026 21:46, Chris M. Thomasson wrote:
    On 10/22/2026 9:54 AM, Kaz Kylheku wrote:
    On 2026-10-22, David Brown <[email protected]> wrote:
    On 21/10/2026 22:02, Chris M. Thomasson wrote:
    On 10/21/2026 5:17 AM, David Brown wrote:
    [...]

    *_t intrudes into POSIX.

    I don't program for POSIX, so I don't care.  The same applies to most >>>>> code that is used in connection with FreeRTOS, or LWIP.  (Of course >>>>> there will be some overlap - bits of code that are intended to run
    on a
    microcontroller but tested with code running native on a PC.)


    Avoiding proclaimed namespaces will not protect you from clashes;
    only from clashes that would occur in those namespaces.

    Some spaces like _t are too attractive to avoid, because they are tied >>>> to an important, popular convention that everyone understands,
    and the benefits outweigh the unrealized risk of a future clash.


    Touche. How about _this vs this_. I just use self and be done with it.

    Imagine, just for a moment, that the rest of us are not privy to the
    jumble of thoughts and ideas that jump around in your head.  I don't
    have the context of what you are thinking about.  So I have no idea
    what you mean by this.

    Instead of posting random out-of-context snippets of thought, either
    write posts that say what you are talking about, or don't bother.
    (And do /not/ imagine that posting reams of unconnected code is a
    useful alternative.)

    If you are trying to say something about avoiding C++ keywords when
    picking identifiers in C coding, say that.  If you are trying to say
    something about naming conventions for C++ class members, feel free to
    talk about that too - in comp.lang.c++.  If you are trying to say
    something else, say it.  Or drop it, if you prefer.


    Or, Well,

    _this

    vs

    this_

    Are they both legal?

    What do you mean, "legal" ? Identifiers in C can start with any letter (including most Unicode "letters") or underscore, or any other implementation-defined characters. Subsequent characters can be any of
    these or a normal digit from the basic source character set.

    The only identifiers you may not use are ones that match keywords.

    There are various patterns that are "reserved", depending on header
    usage, but using them is still "legal". The main ones to avoid are identifiers starting with two underscores, or one underscore and a
    capital letter.


    I like self.

    void foo(struct foo* const self);

    vs

    void foo(struct foo* const _this);
    void foo(struct foo* const this);
    void foo(struct foo* const this_);

    ? For some reason I do not want to use this in C.


    Use whichever you like. I would personally avoid using an identifier in
    C that matches a keyword (or "contextual keyword") in C++, to make it
    easier to re-use the same code in C++. But you don't have to do the same.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@[email protected] to comp.lang.c on Sat Oct 24 22:26:26 2026
    From Newsgroup: comp.lang.c

    On Fri, 23 Oct 2026 18:33:56 -0700, Chris M. Thomasson wrote:

    On 10/23/2026 3:40 PM, Lawrence D’Oliveiro wrote:

    The trouble with a fixed name is, how do you refer to the instance
    of an outer class?

    Well, self can be internal to the API logic.

    If “self” refers to the current instance of the innermost class, how
    do you refer to an instance of an outer class?
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@[email protected] to comp.lang.c on Sun Oct 25 00:56:43 2026
    From Newsgroup: comp.lang.c

    On 2026-10-25 00:26, Lawrence D’Oliveiro wrote:
    On Fri, 23 Oct 2026 18:33:56 -0700, Chris M. Thomasson wrote:
    On 10/23/2026 3:40 PM, Lawrence D’Oliveiro wrote:

    The trouble with a fixed name is, how do you refer to the instance
    of an outer class?

    Well, self can be internal to the API logic.

    If “self” refers to the current instance of the innermost class, how
    do you refer to an instance of an outer class?

    I'm a bit confused about the intention of this sub-thread in CLC.

    Since you have already been (at least implicitly) referring to
    other languages (by mention of 'self' and 'this') I'd answer the
    question that (in principal) a language could qualify the access;
    for example, Simula has "THIS DerivedClass" or "THIS BaseClass",
    or whatever class in the actual class-path is visible. We could
    also access attributes that need an access qualification by the
    'QUA' keyword to disambiguate names common in base and derived
    classes.

    Still curious about the "plan" (for "C") behind, why asking this.

    Janis

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@[email protected] to comp.lang.c on Sat Oct 24 16:38:53 2026
    From Newsgroup: comp.lang.c

    Lawrence D’Oliveiro <[email protected]d> writes:
    On Fri, 23 Oct 2026 18:33:56 -0700, Chris M. Thomasson wrote:
    On 10/23/2026 3:40 PM, Lawrence D’Oliveiro wrote:
    The trouble with a fixed name is, how do you refer to the instance
    of an outer class?

    Well, self can be internal to the API logic.

    If “self” refers to the current instance of the innermost class, how
    do you refer to an instance of an outer class?

    What's a "class"?

    There are ways to implement or simulate classes and inheritance in C.
    Without knowing how that's being done, it's not very meaningful to ask
    how to refer to an instance of an outer class.
    --
    Keith Thompson (The_Other_Keith) [email protected]
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Chris M. Thomasson@[email protected] to comp.lang.c on Sat Oct 24 21:42:50 2026
    From Newsgroup: comp.lang.c

    On 10/24/2026 3:58 AM, David Brown wrote:
    On 23/10/2026 23:21, Chris M. Thomasson wrote:
    On 10/23/2026 12:37 AM, David Brown wrote:
    On 22/10/2026 21:46, Chris M. Thomasson wrote:
    On 10/22/2026 9:54 AM, Kaz Kylheku wrote:
    On 2026-10-22, David Brown <[email protected]> wrote:
    On 21/10/2026 22:02, Chris M. Thomasson wrote:
    On 10/21/2026 5:17 AM, David Brown wrote:
    [...]

    *_t intrudes into POSIX.

    I don't program for POSIX, so I don't care.  The same applies to most >>>>>> code that is used in connection with FreeRTOS, or LWIP.  (Of course >>>>>> there will be some overlap - bits of code that are intended to run >>>>>> on a
    microcontroller but tested with code running native on a PC.)


    Avoiding proclaimed namespaces will not protect you from clashes;
    only from clashes that would occur in those namespaces.

    Some spaces like _t are too attractive to avoid, because they are tied >>>>> to an important, popular convention that everyone understands,
    and the benefits outweigh the unrealized risk of a future clash.


    Touche. How about _this vs this_. I just use self and be done with it.

    Imagine, just for a moment, that the rest of us are not privy to the
    jumble of thoughts and ideas that jump around in your head.  I don't
    have the context of what you are thinking about.  So I have no idea
    what you mean by this.

    Instead of posting random out-of-context snippets of thought, either
    write posts that say what you are talking about, or don't bother.
    (And do /not/ imagine that posting reams of unconnected code is a
    useful alternative.)

    If you are trying to say something about avoiding C++ keywords when
    picking identifiers in C coding, say that.  If you are trying to say
    something about naming conventions for C++ class members, feel free
    to talk about that too - in comp.lang.c++.  If you are trying to say
    something else, say it.  Or drop it, if you prefer.


    Or, Well,

    _this

    vs

    this_

    Are they both legal?

    What do you mean, "legal" ?  Identifiers in C can start with any letter (including most Unicode "letters") or underscore, or any other implementation-defined characters.  Subsequent characters can be any of these or a normal digit from the basic source character set.

    The only identifiers you may not use are ones that match keywords.

    There are various patterns that are "reserved", depending on header
    usage, but using them is still "legal".  The main ones to avoid are identifiers starting with two underscores, or one underscore and a
    capital letter.


    I like self.

    void foo(struct foo* const self);

    vs

    void foo(struct foo* const _this);
    void foo(struct foo* const this);
    void foo(struct foo* const this_);

    ? For some reason I do not want to use this in C.


    Use whichever you like.  I would personally avoid using an identifier in
    C that matches a keyword (or "contextual keyword") in C++, to make it
    easier to re-use the same code in C++.  But you don't have to do the same.


    _this good, _This bad?
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@[email protected] to comp.lang.c on Sun Oct 25 10:51:40 2026
    From Newsgroup: comp.lang.c

    On 25/10/2026 05:42, Chris M. Thomasson wrote:
    On 10/24/2026 3:58 AM, David Brown wrote:
    On 23/10/2026 23:21, Chris M. Thomasson wrote:
    On 10/23/2026 12:37 AM, David Brown wrote:
    On 22/10/2026 21:46, Chris M. Thomasson wrote:
    On 10/22/2026 9:54 AM, Kaz Kylheku wrote:
    On 2026-10-22, David Brown <[email protected]> wrote:
    On 21/10/2026 22:02, Chris M. Thomasson wrote:
    On 10/21/2026 5:17 AM, David Brown wrote:
    [...]

    *_t intrudes into POSIX.

    I don't program for POSIX, so I don't care.  The same applies to >>>>>>> most
    code that is used in connection with FreeRTOS, or LWIP.  (Of course >>>>>>> there will be some overlap - bits of code that are intended to
    run on a
    microcontroller but tested with code running native on a PC.)


    Avoiding proclaimed namespaces will not protect you from clashes;
    only from clashes that would occur in those namespaces.

    Some spaces like _t are too attractive to avoid, because they are >>>>>> tied
    to an important, popular convention that everyone understands,
    and the benefits outweigh the unrealized risk of a future clash.


    Touche. How about _this vs this_. I just use self and be done with it. >>>>
    Imagine, just for a moment, that the rest of us are not privy to the
    jumble of thoughts and ideas that jump around in your head.  I don't >>>> have the context of what you are thinking about.  So I have no idea
    what you mean by this.

    Instead of posting random out-of-context snippets of thought, either
    write posts that say what you are talking about, or don't bother.
    (And do /not/ imagine that posting reams of unconnected code is a
    useful alternative.)

    If you are trying to say something about avoiding C++ keywords when
    picking identifiers in C coding, say that.  If you are trying to say >>>> something about naming conventions for C++ class members, feel free
    to talk about that too - in comp.lang.c++.  If you are trying to say >>>> something else, say it.  Or drop it, if you prefer.


    Or, Well,

    _this

    vs

    this_

    Are they both legal?

    What do you mean, "legal" ?  Identifiers in C can start with any
    letter (including most Unicode "letters") or underscore, or any other
    implementation-defined characters.  Subsequent characters can be any
    of these or a normal digit from the basic source character set.

    The only identifiers you may not use are ones that match keywords.

    There are various patterns that are "reserved", depending on header
    usage, but using them is still "legal".  The main ones to avoid are
    identifiers starting with two underscores, or one underscore and a
    capital letter.


    I like self.

    void foo(struct foo* const self);

    vs

    void foo(struct foo* const _this);
    void foo(struct foo* const this);
    void foo(struct foo* const this_);

    ? For some reason I do not want to use this in C.


    Use whichever you like.  I would personally avoid using an identifier
    in C that matches a keyword (or "contextual keyword") in C++, to make
    it easier to re-use the same code in C++.  But you don't have to do
    the same.


    _this good, _This bad?

    You figure it out. I'm done trying to understand your silly little
    posts and silly little questions, and then spoon-feed you basics about
    the C language.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@[email protected] to comp.lang.c on Sun Oct 25 20:30:32 2026
    From Newsgroup: comp.lang.c

    On Sat, 24 Oct 2026 21:42:50 -0700, Chris M. Thomasson wrote:

    _this good, _This bad?

    If asked “how many letters are there in the English alphabet?”, what
    answer do you think (normal) people are more likely to give: “26” or “52”?

    I think the instinctive answer most people would give is “26”.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Chris M. Thomasson@[email protected] to comp.lang.c on Sun Oct 25 13:54:31 2026
    From Newsgroup: comp.lang.c

    On 10/25/2026 2:51 AM, David Brown wrote:
    On 25/10/2026 05:42, Chris M. Thomasson wrote:
    On 10/24/2026 3:58 AM, David Brown wrote:
    On 23/10/2026 23:21, Chris M. Thomasson wrote:
    On 10/23/2026 12:37 AM, David Brown wrote:
    On 22/10/2026 21:46, Chris M. Thomasson wrote:
    On 10/22/2026 9:54 AM, Kaz Kylheku wrote:
    On 2026-10-22, David Brown <[email protected]> wrote:
    On 21/10/2026 22:02, Chris M. Thomasson wrote:
    On 10/21/2026 5:17 AM, David Brown wrote:
    [...]

    *_t intrudes into POSIX.

    I don't program for POSIX, so I don't care.  The same applies to >>>>>>>> most
    code that is used in connection with FreeRTOS, or LWIP.  (Of course >>>>>>>> there will be some overlap - bits of code that are intended to >>>>>>>> run on a
    microcontroller but tested with code running native on a PC.)


    Avoiding proclaimed namespaces will not protect you from clashes; >>>>>>> only from clashes that would occur in those namespaces.

    Some spaces like _t are too attractive to avoid, because they are >>>>>>> tied
    to an important, popular convention that everyone understands,
    and the benefits outweigh the unrealized risk of a future clash. >>>>>>>

    Touche. How about _this vs this_. I just use self and be done with >>>>>> it.

    Imagine, just for a moment, that the rest of us are not privy to
    the jumble of thoughts and ideas that jump around in your head.  I >>>>> don't have the context of what you are thinking about.  So I have
    no idea what you mean by this.

    Instead of posting random out-of-context snippets of thought,
    either write posts that say what you are talking about, or don't
    bother. (And do /not/ imagine that posting reams of unconnected
    code is a useful alternative.)

    If you are trying to say something about avoiding C++ keywords when >>>>> picking identifiers in C coding, say that.  If you are trying to
    say something about naming conventions for C++ class members, feel
    free to talk about that too - in comp.lang.c++.  If you are trying >>>>> to say something else, say it.  Or drop it, if you prefer.


    Or, Well,

    _this

    vs

    this_

    Are they both legal?

    What do you mean, "legal" ?  Identifiers in C can start with any
    letter (including most Unicode "letters") or underscore, or any other
    implementation-defined characters.  Subsequent characters can be any
    of these or a normal digit from the basic source character set.

    The only identifiers you may not use are ones that match keywords.

    There are various patterns that are "reserved", depending on header
    usage, but using them is still "legal".  The main ones to avoid are
    identifiers starting with two underscores, or one underscore and a
    capital letter.


    I like self.

    void foo(struct foo* const self);

    vs

    void foo(struct foo* const _this);
    void foo(struct foo* const this);
    void foo(struct foo* const this_);

    ? For some reason I do not want to use this in C.


    Use whichever you like.  I would personally avoid using an identifier
    in C that matches a keyword (or "contextual keyword") in C++, to make
    it easier to re-use the same code in C++.  But you don't have to do
    the same.


    _this good, _This bad?

    You figure it out.  I'm done trying to understand your silly little
    posts and silly little questions, and then spoon-feed you basics about
    the C language.


    I already know, just like *_t can be bad. Just shooting the breeze. No
    need to get pissed off.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From fir@[email protected] to comp.lang.c on Mon Oct 26 13:07:17 2026
    From Newsgroup: comp.lang.c

    fir pisze:
    if {} or if {} or if {} else {}


    this form in fact is not bad, it simply showst two things

    1) you may use or outside the if clause (if this () can be named clause)

    2) else in fact work on logical group but ias sole if is alos a case of logical group so else work on it sole in special case

    otherwiste thse keywords here if or and else are quite 'legit'



    if () {}
    or if () {}
    or if() {}
    else {}


    seems quite legit and it seem to ba a switch



    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bartc@[email protected] to comp.lang.c on Mon Oct 26 12:11:48 2026
    From Newsgroup: comp.lang.c

    On 26/10/2026 12:07, fir wrote:
    fir pisze:
    if {} or if {} or if {} else {}


    this form in fact is not bad, it simply showst two things

    1) you may use or outside the if clause (if this () can be named clause)

    2) else in fact work on logical group but ias sole if is alos a case of logical group so else work on it sole in special case

    otherwiste thse keywords here if or and else are quite 'legit'



    if () {}
    or if () {}
    or if() {}
    else {}


    seems quite legit and it seem to ba a switch
    Excellent. A great thing about this is, this can also be legal C, that
    works now, if you just precede with this:

    #define or else


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From fir@[email protected] to comp.lang.c on Mon Oct 26 13:20:49 2026
    From Newsgroup: comp.lang.c

    bartc pisze:
    On 26/10/2026 12:07, fir wrote:
    fir pisze:
    if {} or if {} or if {} else {}


    this form in fact is not bad, it simply showst two things

    1) you may use or outside the if clause (if this () can be named clause)

    2) else in fact work on logical group but ias sole if is alos a case
    of logical group so else work on it sole in special case

    otherwiste thse keywords here if or and else are quite 'legit'



    if () {}
    or if () {}
    or if() {}
    else {}


    seems quite legit and it seem to ba a switch
    Excellent. A great thing about this is, this can also be legal C, that
    works now, if you just precede with this:

      #define or else

    this wouldnt work imo as far as im aware becouse this last else dont
    work on "group'

    the last else is what i name "otherwise" (its else in all other case"

    above i said the else may be "discovered" as works on group where right
    now its only use on sole if as groups are not defined

    but in sucjh combination as above in clasic C the else dont work on group



    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bartc@[email protected] to comp.lang.c on Mon Oct 26 14:16:16 2026
    From Newsgroup: comp.lang.c

    On 26/10/2026 12:20, fir wrote:
    bartc pisze:
    On 26/10/2026 12:07, fir wrote:
    fir pisze:
    if {} or if {} or if {} else {}


    this form in fact is not bad, it simply showst two things

    1) you may use or outside the if clause (if this () can be named clause) >>>
    2) else in fact work on logical group but ias sole if is alos a case
    of logical group so else work on it sole in special case

    otherwiste thse keywords here if or and else are quite 'legit'



    if () {}
    or if () {}
    or if() {}
    else {}


    seems quite legit and it seem to ba a switch
    Excellent. A great thing about this is, this can also be legal C, that
    works now, if you just precede with this:

       #define or else

    this wouldnt work imo as far as im aware becouse this last else dont
    work on "group'

    This works fine:

    #define or else

    for (int i=0; i<=5; ++i)
    if (i==1) {puts("One");}
    or if (i==2) {puts("Two");}
    or if (i==3) {puts("Three");}
    else {puts("Other");}

    Output is:

    Other
    One
    Two
    Three
    Other
    Other

    The point is you eventually came up with syntax that is actually just C
    but using 'or' in place of 'else'.

    the last else is what i name "otherwise" (its else in all other case"
    You seem to have named it 'else' in your example. In any case it would
    just be a slightly different choice of keyword; it buys you very little.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From fir@[email protected] to comp.lang.c on Mon Oct 26 17:03:11 2026
    From Newsgroup: comp.lang.c

    bartc pisze:
    On 26/10/2026 12:20, fir wrote:
    bartc pisze:
    On 26/10/2026 12:07, fir wrote:
    fir pisze:
    if {} or if {} or if {} else {}


    this form in fact is not bad, it simply showst two things

    1) you may use or outside the if clause (if this () can be named
    clause)

    2) else in fact work on logical group but ias sole if is alos a case
    of logical group so else work on it sole in special case

    otherwiste thse keywords here if or and else are quite 'legit'



    if () {}
    or if () {}
    or if() {}
    else {}


    seems quite legit and it seem to ba a switch
    Excellent. A great thing about this is, this can also be legal C,
    that works now, if you just precede with this:

       #define or else

    this wouldnt work imo as far as im aware becouse this last else dont
    work on "group'

    This works fine:

        #define or else

        for (int i=0; i<=5; ++i)
            if    (i==1) {puts("One");}
            or if (i==2) {puts("Two");}
            or if (i==3) {puts("Three");}
            else         {puts("Other");}

    Output is:

      Other
      One
      Two
      Three
      Other
      Other

    The point is you eventually came up with syntax that is actually just C
    but using 'or' in place of 'else'.

    the last else is what i name "otherwise" (its else in all other case"
    You seem to have named it 'else' in your example. In any case it would
    just be a slightly different choice of keyword; it buys you very little.

    maybe try with like

    case x%2==0 //2 4 6 8 10 12
    case x%3==0 //3 6 9 12
    default // 1 5 7 11 13


    the default should run if none of above cases catch (as i remember coz i
    dont use switch) and thse cases should catch each time


    im maybe talkong about some more general switch here but this general (abstract) it is more important then normal one - as thsi general covers various possible cases

    using if or you can implement i it

    if(x%2==0) {}
    or if(x%3==0) {}
    else {}

    without or (or something analogic) as i understand if im not wrong you cant


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Blaine@[email protected] to comp.lang.c on Mon Oct 26 10:28:04 2026
    From Newsgroup: comp.lang.c

    Lawrence D’Oliveiro wrote:
    On Sat, 24 Oct 2026 21:42:50 -0700, Chris M. Thomasson wrote:

    _this good, _This bad?

    If asked “how many letters are there in the English alphabet?”, what answer do you think (normal) people are more likely to give: “26” or “52”?

    I think the instinctive answer most people would give is “26”.

    They usually give 51 because 'O' is just a bigger 'o'.
    --
    Can you strip away so we may start again?
    "There’s a switch and they don't
    seem authentic or themselves. It
    feels like I’m an unnecessary
    body and it’s a waste of time to
    even be there." -- Grim, playful Blaine.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bartc@[email protected] to comp.lang.c on Mon Oct 26 16:32:57 2026
    From Newsgroup: comp.lang.c

    On 26/10/2026 16:03, fir wrote:
    bartc pisze:
    On 26/10/2026 12:20, fir wrote:
    bartc pisze:
    On 26/10/2026 12:07, fir wrote:
    fir pisze:
    if {} or if {} or if {} else {}


    this form in fact is not bad, it simply showst two things

    1) you may use or outside the if clause (if this () can be named
    clause)

    2) else in fact work on logical group but ias sole if is alos a
    case of logical group so else work on it sole in special case

    otherwiste thse keywords here if or and else are quite 'legit'



    if () {}
    or if () {}
    or if() {}
    else {}


    seems quite legit and it seem to ba a switch
    Excellent. A great thing about this is, this can also be legal C,
    that works now, if you just precede with this:

       #define or else

    this wouldnt work imo as far as im aware becouse this last else dont
    work on "group'

    This works fine:

         #define or else

         for (int i=0; i<=5; ++i)
             if    (i==1) {puts("One");}
             or if (i==2) {puts("Two");}
             or if (i==3) {puts("Three");}
             else         {puts("Other");}

    Output is:

       Other
       One
       Two
       Three
       Other
       Other

    The point is you eventually came up with syntax that is actually just
    C but using 'or' in place of 'else'.

    the last else is what i name "otherwise" (its else in all other case"
    You seem to have named it 'else' in your example. In any case it would
    just be a slightly different choice of keyword; it buys you very little.

    maybe try with like

    case x%2==0 //2 4 6 8 10 12
    case x%3==0 //3 6 9 12

    No, cases '6' and '12' are also true for x%2==0. Unless you want these
    to be non-exclusive?

    default  // 1 5 7 11 13


    the default should run if none of above cases catch (as i remember coz i dont use switch) and  thse cases  should catch each time

    OK. C doesn't have a direct syntax for this. But it does have if-else
    chains for precisely this job. What is the problem with that? You can
    write it like this if you like:

    if (0)
    else if (x%2==0) {}
    else if (x%3==0) {}

    if you want consistency. There's no point in creating a slightly
    different syntax for the same thing.

    im maybe talkong about some more general switch here

    What does 'switch' mean to you? It seems that every day it is something
    with more and more capabilities and it gets more ambiguous. At some
    point it will its own AI to divine your intentions.

    but this general
    (abstract) it is more important then normal one - as thsi general covers various possible cases

    using if or you can implement i it

       if(x%2==0) {}
    or if(x%3==0) {}
    else {}

    without or (or something analogic) as i understand if im not wrong you cant
    You seem fixated on that 'or'. Either use 'else', or create 'or' as an
    alias as I suggested.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From fir@[email protected] to comp.lang.c on Mon Oct 26 17:37:53 2026
    From Newsgroup: comp.lang.c

    bartc pisze:
    On 26/10/2026 16:03, fir wrote:
    bartc pisze:
    On 26/10/2026 12:20, fir wrote:
    bartc pisze:
    On 26/10/2026 12:07, fir wrote:
    fir pisze:
    if {} or if {} or if {} else {}


    this form in fact is not bad, it simply showst two things

    1) you may use or outside the if clause (if this () can be named
    clause)

    2) else in fact work on logical group but ias sole if is alos a
    case of logical group so else work on it sole in special case

    otherwiste thse keywords here if or and else are quite 'legit'



    if () {}
    or if () {}
    or if() {}
    else {}


    seems quite legit and it seem to ba a switch
    Excellent. A great thing about this is, this can also be legal C,
    that works now, if you just precede with this:

       #define or else

    this wouldnt work imo as far as im aware becouse this last else dont
    work on "group'

    This works fine:

         #define or else

         for (int i=0; i<=5; ++i)
             if    (i==1) {puts("One");}
             or if (i==2) {puts("Two");}
             or if (i==3) {puts("Three");}
             else         {puts("Other");}

    Output is:

       Other
       One
       Two
       Three
       Other
       Other

    The point is you eventually came up with syntax that is actually just
    C but using 'or' in place of 'else'.

    the last else is what i name "otherwise" (its else in all other case"
    You seem to have named it 'else' in your example. In any case it
    would just be a slightly different choice of keyword; it buys you
    very little.

    maybe try with like

    case x%2==0 //2 4 6 8 10 12
    case x%3==0 //3 6 9 12

    No, cases '6' and '12' are also true for x%2==0. Unless you want these
    to be non-exclusive?

    default  // 1 5 7 11 13


    the default should run if none of above cases catch (as i remember coz
    i dont use switch) and  thse cases  should catch each time

    OK. C doesn't have a direct syntax for this. But it does have if-else
    chains for precisely this job. What is the problem with that? You can
    write it like this if you like:

       if (0)
       else if (x%2==0) {}
       else if (x%3==0) {}

    you want it the above to pront "divides by 2" "divides by 3" for 6 and
    12 "divides by 2" for 4 8 and 'divided by 3" for 2 9 in case it not
    divides by 2 or 3 pronts "no divides "

    this above will not work for 6 for example as it only will prit "divides
    by 2"


    if you want consistency. There's no point in creating a slightly
    different syntax for the same thing.

    im maybe talkong about some more general switch here

    What does 'switch' mean to you? It seems that every day it is something
    with more and more capabilities and it gets more ambiguous. At some
    point it will its own AI to divine your intentions.

     but this general
    (abstract) it is more important then normal one - as thsi general
    covers various possible cases

    using if or you can implement i it

        if(x%2==0) {}
    or if(x%3==0) {}
    else {}

    without or (or something analogic) as i understand if im not wrong you
    cant
    You seem fixated on that 'or'. Either use 'else', or create 'or' as an
    alias as I suggested.



    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bartc@[email protected] to comp.lang.c on Mon Oct 26 16:42:56 2026
    From Newsgroup: comp.lang.c

    On 26/10/2026 16:37, fir wrote:
    bartc pisze:
    On 26/10/2026 16:03, fir wrote:
    bartc pisze:
    On 26/10/2026 12:20, fir wrote:
    bartc pisze:
    On 26/10/2026 12:07, fir wrote:
    fir pisze:
    if {} or if {} or if {} else {}


    this form in fact is not bad, it simply showst two things

    1) you may use or outside the if clause (if this () can be named >>>>>>> clause)

    2) else in fact work on logical group but ias sole if is alos a >>>>>>> case of logical group so else work on it sole in special case

    otherwiste thse keywords here if or and else are quite 'legit'



    if () {}
    or if () {}
    or if() {}
    else {}


    seems quite legit and it seem to ba a switch
    Excellent. A great thing about this is, this can also be legal C, >>>>>> that works now, if you just precede with this:

       #define or else

    this wouldnt work imo as far as im aware becouse this last else
    dont work on "group'

    This works fine:

         #define or else

         for (int i=0; i<=5; ++i)
             if    (i==1) {puts("One");}
             or if (i==2) {puts("Two");}
             or if (i==3) {puts("Three");}
             else         {puts("Other");}

    Output is:

       Other
       One
       Two
       Three
       Other
       Other

    The point is you eventually came up with syntax that is actually
    just C but using 'or' in place of 'else'.

    the last else is what i name "otherwise" (its else in all other case" >>>> You seem to have named it 'else' in your example. In any case it
    would just be a slightly different choice of keyword; it buys you
    very little.

    maybe try with like

    case x%2==0 //2 4 6 8 10 12
    case x%3==0 //3 6 9 12

    No, cases '6' and '12' are also true for x%2==0. Unless you want these
    to be non-exclusive?

    default  // 1 5 7 11 13


    the default should run if none of above cases catch (as i remember
    coz i dont use switch) and  thse cases  should catch each time

    OK. C doesn't have a direct syntax for this. But it does have if-else
    chains for precisely this job. What is the problem with that? You can
    write it like this if you like:

        if (0)
        else if (x%2==0) {}
        else if (x%3==0) {}

    you want it the above to pront "divides by 2" "divides by 3" for 6 and
    12 "divides by 2" for 4 8 and 'divided by 3" for 2 9 in case it not
    divides by 2 or 3 pronts "no divides "

    this above will not work for 6 for example as it only will prit "divides
    by 2"

    So, non-exclusive. That is not clear from your case{} case{} syntax.
    Then it's even simpler:

    if (x%2==0) {}
    if (x%3==0) {}

    Here it is clear they are non-exclusive.

    You're also in luck: this is exactly how C works now!

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From fir@[email protected] to comp.lang.c on Mon Oct 26 17:45:15 2026
    From Newsgroup: comp.lang.c

    bartc pisze:
    without or (or something analogic) as i understand if im not wrong you
    cant
    You seem fixated on that 'or'. Either use 'else', or create 'or' as an
    alias as I suggested.

    imo you should try to understand the example

    for(int i = 1; i < 20; i++)
    {

    if(x%2==0) printf("\n divides by 2");
    or if(x%3==0) printf("\n divides by 3");
    else printf("\n no divides (by 2 or 3)");
    }

    you understand how this would work? i think you do

    and how in normal c without this "or" it would look,
    for exampel in your if else model?
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bartc@[email protected] to comp.lang.c on Mon Oct 26 17:00:05 2026
    From Newsgroup: comp.lang.c

    On 26/10/2026 16:45, fir wrote:
    bartc pisze:
    without or (or something analogic) as i understand if im not wrong
    you cant
    You seem fixated on that 'or'. Either use 'else', or create 'or' as an
    alias as I suggested.

    imo you should try to understand the example

    for(int i = 1; i < 20; i++)
    {

            if(x%2==0) printf("\n divides by 2");
         or if(x%3==0) printf("\n divides by 3");
         else  printf("\n no divides (by 2 or 3)");
    }

    you understand how this would work? i think you do

    and how in normal c without this "or" it would look,
    for exampel in your if else model?

    Show me exactly what the output should be, when it is written like this:

    if(x%2==0) printf("\n%d divides by 2", i);
    or if(x%3==0) printf("\n%d divides by 3", i);
    else printf("\n%d no divides (by 2 or 3)", i);

    You might also want to look at the FizzBuzz program.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From fir@[email protected] to comp.lang.c on Mon Oct 26 18:06:51 2026
    From Newsgroup: comp.lang.c

    bartc pisze:
    On 26/10/2026 16:45, fir wrote:
    bartc pisze:
    without or (or something analogic) as i understand if im not wrong
    you cant
    You seem fixated on that 'or'. Either use 'else', or create 'or' as
    an alias as I suggested.

    imo you should try to understand the example

    for(int i = 1; i < 20; i++)
    {

             if(x%2==0) printf("\n divides by 2");
          or if(x%3==0) printf("\n divides by 3");
          else  printf("\n no divides (by 2 or 3)");
    }

    you understand how this would work? i think you do

    and how in normal c without this "or" it would look,
    for exampel in your if else model?

    Show me exactly what the output should be, when it is written like this:

              if(x%2==0) printf("\n%d divides by 2", i);
           or if(x%3==0) printf("\n%d divides by 3", i);
           else  printf("\n%d no divides (by 2 or 3)", i);

    You might also want to look at the FizzBuzz program.

    1 no divides (by 2 or 3)
    2 divides by 2
    3 divides by 3
    4 divides by 2
    5 no divides (by 2 or 3)
    6 divides by 2
    6 divides by 3
    7 no divides (by 2 or 3)
    8 divides by 2
    9 divides by 3
    10 divides by 2
    11 no divides (by 2 or 3)
    12 divides by 2
    12 divides by 3
    13 no divides (by 2 or 3)
    14 divides by 2
    15 divides by 3
    16 divides by 2
    17 no divides (by 2 or 3)
    18 divides by 2
    18 divides by 3
    19 no divides (by 2 or 3)

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From fir@[email protected] to comp.lang.c on Mon Oct 26 18:11:11 2026
    From Newsgroup: comp.lang.c

    fir pisze:
    bartc pisze:
    On 26/10/2026 16:45, fir wrote:
    bartc pisze:
    without or (or something analogic) as i understand if im not wrong
    you cant
    You seem fixated on that 'or'. Either use 'else', or create 'or' as
    an alias as I suggested.

    imo you should try to understand the example

    for(int i = 1; i < 20; i++)
    {

             if(x%2==0) printf("\n divides by 2");
          or if(x%3==0) printf("\n divides by 3");
          else  printf("\n no divides (by 2 or 3)");
    }

    you understand how this would work? i think you do

    and how in normal c without this "or" it would look,
    for exampel in your if else model?

    Show me exactly what the output should be, when it is written like this:

               if(x%2==0) printf("\n%d divides by 2", i);
            or if(x%3==0) printf("\n%d divides by 3", i);
            else  printf("\n%d no divides (by 2 or 3)", i);

    You might also want to look at the FizzBuzz program.

    1 no divides (by 2 or 3)
    2 divides by 2
    3 divides by 3
    4 divides by 2
    5 no divides (by 2 or 3)
    6 divides by 2
    6 divides by 3
    7 no divides (by 2 or 3)
    8 divides by 2
    9 divides by 3
    10 divides by 2
    11 no divides (by 2 or 3)
    12 divides by 2
    12 divides by 3
    13 no divides (by 2 or 3)
    14 divides by 2
    15 divides by 3
    16 divides by 2
    17 no divides (by 2 or 3)
    18 divides by 2
    18 divides by 3
    19 no divides (by 2 or 3)




    in fact i had more such in my mind

    for(int i=0; i<20; i++)
    {
    printf("\n %d,i);
    if(x%2==0) printf("\n divides by 2");
    or if(x%3==0) printf("\n divides by 3");
    else printf("\n no divides (by 2 or 3)");

    }

    so the output is
    1
    no divides (by 2 or 3)
    2
    divides by 2
    3
    divides by 3
    4
    divides by 2
    5
    no divides (by 2 or 3)
    6
    divides by 2
    divides by 3
    7
    no divides (by 2 or 3)
    8
    divides by 2
    9
    divides by 3
    10
    divides by 2
    11
    no divides (by 2 or 3)
    12
    divides by 2
    divides by 3
    13
    no divides (by 2 or 3)
    14
    divides by 2
    15
    divides by 3
    16
    divides by 2
    17
    no divides (by 2 or 3)
    18
    divides by 2
    divides by 3
    19
    no divides (by 2 or 3)

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From fir@[email protected] to comp.lang.c on Mon Oct 26 18:37:04 2026
    From Newsgroup: comp.lang.c

    fir pisze:
    fir pisze:
    bartc pisze:
    On 26/10/2026 16:45, fir wrote:
    bartc pisze:
    without or (or something analogic) as i understand if im not wrong >>>>>> you cant
    You seem fixated on that 'or'. Either use 'else', or create 'or' as >>>>> an alias as I suggested.

    imo you should try to understand the example

    for(int i = 1; i < 20; i++)
    {

             if(x%2==0) printf("\n divides by 2");
          or if(x%3==0) printf("\n divides by 3");
          else  printf("\n no divides (by 2 or 3)");
    }

    you understand how this would work? i think you do

    and how in normal c without this "or" it would look,
    for exampel in your if else model?

    Show me exactly what the output should be, when it is written like this: >>>
               if(x%2==0) printf("\n%d divides by 2", i);
            or if(x%3==0) printf("\n%d divides by 3", i);
            else  printf("\n%d no divides (by 2 or 3)", i);

    You might also want to look at the FizzBuzz program.

    1 no divides (by 2 or 3)
    2 divides by 2
    3 divides by 3
    4 divides by 2
    5 no divides (by 2 or 3)
    6 divides by 2
    6 divides by 3
    7 no divides (by 2 or 3)
    8 divides by 2
    9 divides by 3
    10 divides by 2
    11 no divides (by 2 or 3)
    12 divides by 2
    12 divides by 3
    13 no divides (by 2 or 3)
    14 divides by 2
    15 divides by 3
    16 divides by 2
    17 no divides (by 2 or 3)
    18 divides by 2
    18 divides by 3
    19 no divides (by 2 or 3)




    in fact i had more such in my mind

    for(int i=0; i<20; i++)
    {
    printf("\n %d,i);
    if(x%2==0) printf("\n divides by 2");
     or if(x%3==0) printf("\n divides by 3");
     else printf("\n no divides (by 2 or 3)");

    }

    so the output is
     1
     no divides (by 2 or 3)
     2
     divides by 2
     3
     divides by 3
     4
     divides by 2
     5
     no divides (by 2 or 3)
     6
     divides by 2
     divides by 3
     7
     no divides (by 2 or 3)
     8
     divides by 2
     9
     divides by 3
     10
     divides by 2
     11
     no divides (by 2 or 3)
     12
     divides by 2
     divides by 3
     13
     no divides (by 2 or 3)
     14
     divides by 2
     15
     divides by 3
     16
     divides by 2
     17
     no divides (by 2 or 3)
     18
     divides by 2
     divides by 3
     19
     no divides (by 2 or 3)


    ...and.....?
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@[email protected] to comp.lang.c on Mon Oct 26 19:39:59 2026
    From Newsgroup: comp.lang.c

    On 2026-10-26 17:42, bartc wrote:
    On 26/10/2026 16:37, fir wrote:
    bartc pisze:
    On 26/10/2026 16:03, fir wrote:
    bartc pisze:
    On 26/10/2026 12:20, fir wrote:
    bartc pisze:
    On 26/10/2026 12:07, fir wrote:
    fir pisze:
    if {} or if {} or if {} else {}
    [...]
    if () {}
    or if () {}
    or if() {}
    else {}
    [...]
         #define or else

         for (int i=0; i<=5; ++i)
             if    (i==1) {puts("One");}
             or if (i==2) {puts("Two");}
             or if (i==3) {puts("Three");}
             else         {puts("Other");}
    [...]
    case x%2==0 //2 4 6 8 10 12
    case x%3==0 //3 6 9 12
    default  // 1 5 7 11 13
    [...]
        if (0)
        else if (x%2==0) {}
        else if (x%3==0) {}
    [...]
      if (x%2==0) {}
      if (x%3==0) {}

    Here it is clear they are non-exclusive.

    You're also in luck: this is exactly how C works now!

    I'm not sure what fir actually wants; I cannot decipher his writings
    quoted by you. But, given that he not yet seems satisfied with your
    replies and suggestions, could it, by any chance, be that what he
    wants is some non-deterministic construct like Dijkstra's Guards?

    I.e., that with two guards 'x%2==0' and 'x%3==0' and an input of "6"
    only _one_ of the two gets _arbitrarily_ triggered?

    (Otherwise his post appears quite pointless to me.)

    Janis

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From fir@[email protected] to comp.lang.c on Mon Oct 26 20:03:20 2026
    From Newsgroup: comp.lang.c

    Janis Papanagnou pisze:
    On 2026-10-26 17:42, bartc wrote:
    On 26/10/2026 16:37, fir wrote:
    bartc pisze:
    On 26/10/2026 16:03, fir wrote:
    bartc pisze:
    On 26/10/2026 12:20, fir wrote:
    bartc pisze:
    On 26/10/2026 12:07, fir wrote:
    fir pisze:
    if {} or if {} or if {} else {}
    [...]
    if () {}
    or if () {}
    or if() {}
    else {}
    [...]
         #define or else

         for (int i=0; i<=5; ++i)
             if    (i==1) {puts("One");}
             or if (i==2) {puts("Two");}
             or if (i==3) {puts("Three");}
             else         {puts("Other");}
    [...]
    case x%2==0 //2 4 6 8 10 12
    case x%3==0 //3 6 9 12
    default  // 1 5 7 11 13
    [...]
        if (0)
        else if (x%2==0) {}
        else if (x%3==0) {}
    [...]
       if (x%2==0) {}
       if (x%3==0) {}

    Here it is clear they are non-exclusive.

    You're also in luck: this is exactly how C works now!

    I'm not sure what fir actually wants; I cannot decipher his writings
    quoted by you. But, given that he not yet seems satisfied with your
    replies and suggestions, could it, by any chance, be that what he
    wants is some non-deterministic construct like Dijkstra's Guards?

    I.e., that with two guards 'x%2==0' and 'x%3==0' and an input of "6"
    only _one_ of the two gets _arbitrarily_ triggered?

    (Otherwise his post appears quite pointless to me.)

    Janis



    i quite defined the problem see the simple program


    for(int i=0; i<20; i++)
    {
    printf("\n %d,i);

    if(x%2==0)
    printf("\n divides by 2");
    or if(x%3==0)
    printf("\n divides by 3");
    else
    printf("\n no divides (by 2 or 3)");

    }

    keyword or resloves problem here the problem is if you add or the else
    works on grpup of previous ifs

    here in cases

    0 or 0 else {}
    1 or 0 else {}
    0 or 1 else {}
    1 or 1 else {}


    else works on fales so here olse works like default
    in switch only on all zeros


    write such above program without or so it giver the desired result


    1
    no divides (by 2 or 3)
    2
    divides by 2
    3
    divides by 3
    4
    divides by 2
    5
    no divides (by 2 or 3)
    6
    divides by 2
    divides by 3
    7
    no divides (by 2 or 3)
    8
    divides by 2
    9
    divides by 3
    10
    divides by 2
    11
    no divides (by 2 or 3)
    12
    divides by 2
    divides by 3
    13
    no divides (by 2 or 3)
    14
    divides by 2
    15
    divides by 3
    16
    divides by 2
    17
    no divides (by 2 or 3)
    18
    divides by 2
    divides by 3
    19
    no divides (by 2 or 3)

    my thoughts are general as o abstract switch concept and its a bit multidimensional ;c maybe but specifically
    ut shows that if and elses not cover all logical cases when
    if you add such or and and (or some different analogies) those cases
    would be covered
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bartc@[email protected] to comp.lang.c on Mon Oct 26 19:03:55 2026
    From Newsgroup: comp.lang.c

    On 26/10/2026 17:06, fir wrote:
    bartc pisze:
    On 26/10/2026 16:45, fir wrote:
    bartc pisze:
    without or (or something analogic) as i understand if im not wrong
    you cant
    You seem fixated on that 'or'. Either use 'else', or create 'or' as
    an alias as I suggested.

    imo you should try to understand the example

    for(int i = 1; i < 20; i++)
    {

             if(x%2==0) printf("\n divides by 2");
          or if(x%3==0) printf("\n divides by 3");
          else  printf("\n no divides (by 2 or 3)");
    }

    you understand how this would work? i think you do

    and how in normal c without this "or" it would look,
    for exampel in your if else model?

    Show me exactly what the output should be, when it is written like this:

               if(x%2==0) printf("\n%d divides by 2", i);
            or if(x%3==0) printf("\n%d divides by 3", i);
            else  printf("\n%d no divides (by 2 or 3)", i);

    You might also want to look at the FizzBuzz program.

    1 no divides (by 2 or 3)
    2 divides by 2
    3 divides by 3
    4 divides by 2
    5 no divides (by 2 or 3)
    6 divides by 2
    6 divides by 3
    7 no divides (by 2 or 3)
    8 divides by 2
    9 divides by 3
    10 divides by 2
    11 no divides (by 2 or 3)
    12 divides by 2
    12 divides by 3
    13 no divides (by 2 or 3)
    14 divides by 2
    15 divides by 3
    16 divides by 2
    17 no divides (by 2 or 3)
    18 divides by 2
    18 divides by 3
    19 no divides (by 2 or 3)

    OK, thanks. So the pattern you're talking about is this:

    case (c1) {s1}
    case (c2) {s2}
    case (c3) {s3}
    else {s4}

    where each of s1/s2/s3 is executed if the corresponding c1/c2/c3 is
    true, independently of the others. At least one statement will be
    executed in 7 of the 8 possible boolean combinations in this example.

    s4 is only executed when each of c1/c2/c3 is false. In other words:

    if (c1) {s1}
    if (c2) {s2}
    if (c3) {s3}
    if (!c1 && !c2 && !c3) {s4}

    Assuming c1/c2/c3 are not modified by s1/s2/s3, but this is also partly
    the case with your proposal.

    Or maybe it can be done like this:

    if (c1 || c2 || c3) {
    s4
    else if (c1) {s1)
    ....

    The syntax will anyway need some work to tie all those case/if parts
    together (as s2 for example could contain nested versions).

    Or you can forget about having to create a hard-to-grasp and awkward-to-implement feature like this, and either use workarounds like
    my C examples, or use another approach to the problem.



    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From fir@[email protected] to comp.lang.c on Mon Oct 26 20:39:57 2026
    From Newsgroup: comp.lang.c

    bartc pisze:
    On 26/10/2026 17:06, fir wrote:
    bartc pisze:
    On 26/10/2026 16:45, fir wrote:
    bartc pisze:
    without or (or something analogic) as i understand if im not wrong >>>>>> you cant
    You seem fixated on that 'or'. Either use 'else', or create 'or' as >>>>> an alias as I suggested.

    imo you should try to understand the example

    for(int i = 1; i < 20; i++)
    {

             if(x%2==0) printf("\n divides by 2");
          or if(x%3==0) printf("\n divides by 3");
          else  printf("\n no divides (by 2 or 3)");
    }

    you understand how this would work? i think you do

    and how in normal c without this "or" it would look,
    for exampel in your if else model?

    Show me exactly what the output should be, when it is written like this: >>>
               if(x%2==0) printf("\n%d divides by 2", i);
            or if(x%3==0) printf("\n%d divides by 3", i);
            else  printf("\n%d no divides (by 2 or 3)", i);

    You might also want to look at the FizzBuzz program.

    1 no divides (by 2 or 3)
    2 divides by 2
    3 divides by 3
    4 divides by 2
    5 no divides (by 2 or 3)
    6 divides by 2
    6 divides by 3
    7 no divides (by 2 or 3)
    8 divides by 2
    9 divides by 3
    10 divides by 2
    11 no divides (by 2 or 3)
    12 divides by 2
    12 divides by 3
    13 no divides (by 2 or 3)
    14 divides by 2
    15 divides by 3
    16 divides by 2
    17 no divides (by 2 or 3)
    18 divides by 2
    18 divides by 3
    19 no divides (by 2 or 3)

    OK, thanks. So the pattern you're talking about is this:

      case (c1) {s1}
      case (c2) {s2}
      case (c3) {s3}
      else      {s4}

    where each of s1/s2/s3 is executed if the corresponding c1/c2/c3 is
    true, independently of the others. At least one statement will be
    executed in 7 of the 8 possible boolean combinations in this example.

    s4 is only executed when each of c1/c2/c3 is false. In other words:

      if (c1) {s1}
      if (c2) {s2}
      if (c3) {s3}
      if (!c1 && !c2 && !c3) {s4}

    Assuming c1/c2/c3 are not modified by s1/s2/s3, but this is also partly
    the case with your proposal.

    Or maybe it can be done like this:

      if (c1 || c2 || c3) {
          s4
      else if (c1) {s1)
      ....

    The syntax will anyway need some work to tie all those case/if parts together (as s2 for example could contain nested versions).

    Or you can forget about having to create a hard-to-grasp and awkward-to-implement feature like this, and either use workarounds like
    my C examples, or use another approach to the problem.



    hahaha

    lol ye use worakarounds instead of simple right solution
    (this solution may come in some plavours as i said before, but this or
    ketword for reasons mentioned is not bad)
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bartc@[email protected] to comp.lang.c on Mon Oct 26 19:59:28 2026
    From Newsgroup: comp.lang.c

    On 26/10/2026 19:39, fir wrote:
    bartc pisze:

    1 no divides (by 2 or 3)
    2 divides by 2
    3 divides by 3
    4 divides by 2
    5 no divides (by 2 or 3)
    6 divides by 2
    6 divides by 3
    7 no divides (by 2 or 3)
    8 divides by 2
    9 divides by 3
    10 divides by 2
    11 no divides (by 2 or 3)
    12 divides by 2
    12 divides by 3
    13 no divides (by 2 or 3)
    14 divides by 2
    15 divides by 3
    16 divides by 2
    17 no divides (by 2 or 3)
    18 divides by 2
    18 divides by 3
    19 no divides (by 2 or 3)

    OK, thanks. So the pattern you're talking about is this:

       case (c1) {s1}
       case (c2) {s2}
       case (c3) {s3}
       else      {s4}

    where each of s1/s2/s3 is executed if the corresponding c1/c2/c3 is
    true, independently of the others. At least one statement will be
    executed in 7 of the 8 possible boolean combinations in this example.

    s4 is only executed when each of c1/c2/c3 is false. In other words:

       if (c1) {s1}
       if (c2) {s2}
       if (c3) {s3}
       if (!c1 && !c2 && !c3) {s4}

    Assuming c1/c2/c3 are not modified by s1/s2/s3, but this is also
    partly the case with your proposal.

    Or maybe it can be done like this:

       if (c1 || c2 || c3) {
           s4
       else if (c1) {s1)
       ....

    The syntax will anyway need some work to tie all those case/if parts
    together (as s2 for example could contain nested versions).

    Or you can forget about having to create a hard-to-grasp and awkward-
    to-implement feature like this, and either use workarounds like my C
    examples, or use another approach to the problem.



    hahaha

    lol ye use worakarounds instead of simple right solution

    The right solution to what problem? It took multiple posts before you
    even managed to explain how your proposal is supposed to behave.

    (And then tomorrow it'll probably do something else.)

    (this solution may come in some plavours as i said before, but this or ketword for reasons mentioned is not bad)

    OK, try a simple experiment: convert some code using your 'or' keyword
    to regular C syntax and post it here. Preferably on a real example.

    Because I've not convinced it comes up often enough to be worth a
    dedicated feature.

    Then, consider examples like this:

    case (a==b and c==d) {}
    case (a==b and e==f) {}

    case (a<b) {}
    case (a>=b) {}
    case (c==d) {}

    You'll find, when converting to regular C, that detecting the case of
    all false will mean checking all conditions, but now those will contain duplicates. It is hard to cleanly express, which is a bad sign as a prospective language feature.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From fir@[email protected] to comp.lang.c on Mon Oct 26 21:13:38 2026
    From Newsgroup: comp.lang.c

    bartc pisze:
    On 26/10/2026 19:39, fir wrote:
    bartc pisze:

    1 no divides (by 2 or 3)
    2 divides by 2
    3 divides by 3
    4 divides by 2
    5 no divides (by 2 or 3)
    6 divides by 2
    6 divides by 3
    7 no divides (by 2 or 3)
    8 divides by 2
    9 divides by 3
    10 divides by 2
    11 no divides (by 2 or 3)
    12 divides by 2
    12 divides by 3
    13 no divides (by 2 or 3)
    14 divides by 2
    15 divides by 3
    16 divides by 2
    17 no divides (by 2 or 3)
    18 divides by 2
    18 divides by 3
    19 no divides (by 2 or 3)

    OK, thanks. So the pattern you're talking about is this:

       case (c1) {s1}
       case (c2) {s2}
       case (c3) {s3}
       else      {s4}

    where each of s1/s2/s3 is executed if the corresponding c1/c2/c3 is
    true, independently of the others. At least one statement will be
    executed in 7 of the 8 possible boolean combinations in this example.

    s4 is only executed when each of c1/c2/c3 is false. In other words:

       if (c1) {s1}
       if (c2) {s2}
       if (c3) {s3}
       if (!c1 && !c2 && !c3) {s4}

    Assuming c1/c2/c3 are not modified by s1/s2/s3, but this is also
    partly the case with your proposal.

    Or maybe it can be done like this:

       if (c1 || c2 || c3) {
           s4
       else if (c1) {s1)
       ....

    The syntax will anyway need some work to tie all those case/if parts
    together (as s2 for example could contain nested versions).

    Or you can forget about having to create a hard-to-grasp and awkward-
    to-implement feature like this, and either use workarounds like my C
    examples, or use another approach to the problem.



    hahaha

    lol ye use worakarounds instead of simple right solution

    The right solution to what problem? It took multiple posts before you
    even managed to explain how your proposal is supposed to behave.


    well i was surprised how slow you think it is the reason you get things
    slow - and that s why it took multiple posts - still you far from
    getting it more it seems - it may take years maybe ;c

    and i make laugh becouse its funny how some slowly take some things and
    how bad answer thay give - its kinda laughable

    (And then tomorrow it'll probably do something else.)

    (this solution may come in some plavours as i said before, but this or
    ketword for reasons mentioned is not bad)

    OK, try a simple experiment: convert some code using your 'or' keyword
    to regular C syntax and post it here. Preferably on a real example.

    Because I've not convinced it comes up often enough to be worth a
    dedicated feature.

    Then, consider examples like this:

      case (a==b and c==d) {}
      case (a==b and e==f) {}

      case (a<b) {}
      case (a>=b) {}
      case (c==d) {}

    You'll find, when converting to regular C, that detecting the case of
    all false will mean checking all conditions, but now those will contain duplicates. It is hard to cleanly express, which is a bad sign as a prospective language feature.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From fir@[email protected] to comp.lang.c on Mon Oct 26 21:32:06 2026
    From Newsgroup: comp.lang.c

    bartc pisze:
    On 26/10/2026 19:39, fir wrote:
    bartc pisze:

    1 no divides (by 2 or 3)
    2 divides by 2
    3 divides by 3
    4 divides by 2
    5 no divides (by 2 or 3)
    6 divides by 2
    6 divides by 3
    7 no divides (by 2 or 3)
    8 divides by 2
    9 divides by 3
    10 divides by 2
    11 no divides (by 2 or 3)
    12 divides by 2
    12 divides by 3
    13 no divides (by 2 or 3)
    14 divides by 2
    15 divides by 3
    16 divides by 2
    17 no divides (by 2 or 3)
    18 divides by 2
    18 divides by 3
    19 no divides (by 2 or 3)

    OK, thanks. So the pattern you're talking about is this:

       case (c1) {s1}
       case (c2) {s2}
       case (c3) {s3}
       else      {s4}

    where each of s1/s2/s3 is executed if the corresponding c1/c2/c3 is
    true, independently of the others. At least one statement will be
    executed in 7 of the 8 possible boolean combinations in this example.

    s4 is only executed when each of c1/c2/c3 is false. In other words:

       if (c1) {s1}
       if (c2) {s2}
       if (c3) {s3}
       if (!c1 && !c2 && !c3) {s4}

    Assuming c1/c2/c3 are not modified by s1/s2/s3, but this is also
    partly the case with your proposal.

    Or maybe it can be done like this:

       if (c1 || c2 || c3) {
           s4
       else if (c1) {s1)
       ....

    The syntax will anyway need some work to tie all those case/if parts
    together (as s2 for example could contain nested versions).

    Or you can forget about having to create a hard-to-grasp and awkward-
    to-implement feature like this, and either use workarounds like my C
    examples, or use another approach to the problem.



    hahaha

    lol ye use worakarounds instead of simple right solution

    The right solution to what problem? It took multiple posts before you
    even managed to explain how your proposal is supposed to behave.

    (And then tomorrow it'll probably do something else.)

    (this solution may come in some plavours as i said before, but this or
    ketword for reasons mentioned is not bad)

    OK, try a simple experiment: convert some code using your 'or' keyword
    to regular C syntax and post it here. Preferably on a real example.


    you cant properly convert this or/and groups to c in good way becouse
    there is flaw in c you cannot express all needed combinations generally
    with sole if 's and else's

    as was showed here


    Because I've not convinced it comes up often enough to be worth a
    dedicated feature.

    Then, consider examples like this:

      case (a==b and c==d) {}
      case (a==b and e==f) {}

      case (a<b) {}
      case (a>=b) {}
      case (c==d) {}

    You'll find, when converting to regular C, that detecting the case of
    all false will mean checking all conditions, but now those will contain duplicates. It is hard to cleanly express, which is a bad sign as a prospective language feature.


    i dont like get what you talk here..overally this is a work for compiler
    to simplify it in output


    btw you think i should defend the things i was talking about -
    i more see its a waste of time if someone dont understand things
    it is for him if he understoods or not, i have not so much time to
    defend obvious things against the people who not care to much to
    understand things

    i would sy like its taking hours repairing a code that is
    good - whou would like to do it?


    generally such time spanding that you got good code and some weird
    people come nad put a bulshit its wrong and expect me to explain this is
    not its not a good time spending imo

    i would rather expect if some will find some 'bug ' in code then he
    first should understand it
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From fir@[email protected] to comp.lang.c on Mon Oct 26 21:47:26 2026
    From Newsgroup: comp.lang.c

    fir pisze:
    bartc pisze:
    On 26/10/2026 19:39, fir wrote:
    bartc pisze:

    1 no divides (by 2 or 3)
    2 divides by 2
    3 divides by 3
    4 divides by 2
    5 no divides (by 2 or 3)
    6 divides by 2
    6 divides by 3
    7 no divides (by 2 or 3)
    8 divides by 2
    9 divides by 3
    10 divides by 2
    11 no divides (by 2 or 3)
    12 divides by 2
    12 divides by 3
    13 no divides (by 2 or 3)
    14 divides by 2
    15 divides by 3
    16 divides by 2
    17 no divides (by 2 or 3)
    18 divides by 2
    18 divides by 3
    19 no divides (by 2 or 3)

    OK, thanks. So the pattern you're talking about is this:

       case (c1) {s1}
       case (c2) {s2}
       case (c3) {s3}
       else      {s4}

    where each of s1/s2/s3 is executed if the corresponding c1/c2/c3 is
    true, independently of the others. At least one statement will be
    executed in 7 of the 8 possible boolean combinations in this example.

    s4 is only executed when each of c1/c2/c3 is false. In other words:

       if (c1) {s1}
       if (c2) {s2}
       if (c3) {s3}
       if (!c1 && !c2 && !c3) {s4}

    Assuming c1/c2/c3 are not modified by s1/s2/s3, but this is also
    partly the case with your proposal.

    Or maybe it can be done like this:

       if (c1 || c2 || c3) {
           s4
       else if (c1) {s1)
       ....

    The syntax will anyway need some work to tie all those case/if parts
    together (as s2 for example could contain nested versions).

    Or you can forget about having to create a hard-to-grasp and
    awkward- to-implement feature like this, and either use workarounds
    like my C examples, or use another approach to the problem.



    hahaha

    lol ye use worakarounds instead of simple right solution

    The right solution to what problem? It took multiple posts before you
    even managed to explain how your proposal is supposed to behave.

    (And then tomorrow it'll probably do something else.)

    (this solution may come in some plavours as i said before, but this
    or ketword for reasons mentioned is not bad)

    OK, try a simple experiment: convert some code using your 'or' keyword
    to regular C syntax and post it here. Preferably on a real example.


    you cant properly convert this or/and groups to c in good way becouse
    there is flaw in c you cannot express all needed combinations generally
    with sole if 's and else's

    as was showed here


    Because I've not convinced it comes up often enough to be worth a
    dedicated feature.

    Then, consider examples like this:

       case (a==b and c==d) {}
       case (a==b and e==f) {}

       case (a<b) {}
       case (a>=b) {}
       case (c==d) {}

    You'll find, when converting to regular C, that detecting the case of
    all false will mean checking all conditions, but now those will
    contain duplicates. It is hard to cleanly express, which is a bad sign
    as a prospective language feature.


    i dont like get what you talk here..overally this is a work for compiler
    to simplify it in output


    btw you think i should defend the things i was talking about -
    i more see its a waste of time if someone dont understand things
    it is for him if he understoods or not, i have not so much time to
    defend obvious things against the people who not care to much to
    understand things

    i would sy like its taking hours repairing a code that is
    good - whou would like to do it?


    generally such time spanding that you got good code and some weird
    people come nad put a bulshit its wrong and expect me to explain this is
    not its not a good time spending imo

    i would rather expect if some will find some 'bug ' in code then he
    first should understand it

    overally instead of dwelling in this timewaste some could consider more interesting things, for example if normal switch is like

    "some true" then {} else {}



    there could be considered usability of more cases


    "all true" then {} else {}

    "none true" then {} else {}

    "only one true" then {} else {}

    "only one false" then {} else {}

    im not sure as to usability of this but if its usable then
    it maybe can be encoded by more keywords instead of then
    and else

    like

    case a<2 {}
    case a>4 {}
    case a==0 {}
    case none {} //like default
    case all {}
    case some {}

    so it seems that switch can be extended thsi way

    (not sure as to usability of this)




    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bartc@[email protected] to comp.lang.c on Mon Oct 26 20:56:46 2026
    From Newsgroup: comp.lang.c

    On 26/10/2026 20:13, fir wrote:
    bartc pisze:
    On 26/10/2026 19:39, fir wrote:
    bartc pisze:

    1 no divides (by 2 or 3)
    2 divides by 2
    3 divides by 3
    4 divides by 2
    5 no divides (by 2 or 3)
    6 divides by 2
    6 divides by 3
    7 no divides (by 2 or 3)
    8 divides by 2
    9 divides by 3
    10 divides by 2
    11 no divides (by 2 or 3)
    12 divides by 2
    12 divides by 3
    13 no divides (by 2 or 3)
    14 divides by 2
    15 divides by 3
    16 divides by 2
    17 no divides (by 2 or 3)
    18 divides by 2
    18 divides by 3
    19 no divides (by 2 or 3)

    OK, thanks. So the pattern you're talking about is this:

       case (c1) {s1}
       case (c2) {s2}
       case (c3) {s3}
       else      {s4}

    where each of s1/s2/s3 is executed if the corresponding c1/c2/c3 is
    true, independently of the others. At least one statement will be
    executed in 7 of the 8 possible boolean combinations in this example.

    s4 is only executed when each of c1/c2/c3 is false. In other words:

       if (c1) {s1}
       if (c2) {s2}
       if (c3) {s3}
       if (!c1 && !c2 && !c3) {s4}

    Assuming c1/c2/c3 are not modified by s1/s2/s3, but this is also
    partly the case with your proposal.

    Or maybe it can be done like this:

       if (c1 || c2 || c3) {
           s4
       else if (c1) {s1)
       ....

    The syntax will anyway need some work to tie all those case/if parts
    together (as s2 for example could contain nested versions).

    Or you can forget about having to create a hard-to-grasp and
    awkward- to-implement feature like this, and either use workarounds
    like my C examples, or use another approach to the problem.



    hahaha

    lol ye use worakarounds instead of simple right solution

    The right solution to what problem? It took multiple posts before you
    even managed to explain how your proposal is supposed to behave.


    well i was surprised how slow you think it is the reason you get things
    slow - and that s why it took multiple posts

    Mainly from you failing to explain? You wrote comments like this:

    "this wouldnt work imo as far as im aware becouse this last else dont
    work on "group'"

    IMO? It either works or it doesn't, and if not, explain why 'or' was not
    just an alias for 'else'.

    and i make laugh becouse its funny how some slowly take some things and
    how bad answer thay give - its kinda laughable

    Well, this is the thing: given a well-specified, well-thought-out
    feature, I can probably implement it in one of my compilers within a day.

    That can serve as a proof-of-concept, and can be used to see how well it stands up and how useful it actually is.

    This one wouldn't pass that bar. But also, I've not convinced that you
    put much thought into it. If I implemented it, you'd change your mind
    about it, or add new twists, or get bored and think up something else.

    It would be a waste of time.

    So what's the purpose of these hundreds of wacky, random ideas: do you
    expect someone else to implement them for you? If so, in which language?

    Today was a bit of fun, but I can't take your ideas seriously.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bartc@[email protected] to comp.lang.c on Mon Oct 26 21:11:03 2026
    From Newsgroup: comp.lang.c

    On 26/10/2026 20:32, fir wrote:
    bartc pisze:

    OK, try a simple experiment: convert some code using your 'or' keyword
    to regular C syntax and post it here. Preferably on a real example.


    you cant properly convert this or/and groups to c in good way becouse
    there is flaw in c you cannot express all needed combinations generally
    with sole if 's and else's

    as was showed here
    There are a couple of reasons to express it in C:

    * To illustrate exactly how you want the semantics to work, via
    an existing language whose behaviour is well known

    * To highlight the problem areas

    For example:

    if (f1()) {}
    if (f2()) {}
    ...
    if (!f1() && !f2()) {}

    Here f1/f2 are called twice. This means making internal copies or
    setting flags.


    You'll find, when converting to regular C, that detecting the case of
    all false will mean checking all conditions, but now those will
    contain duplicates. It is hard to cleanly express, which is a bad sign
    as a prospective language feature.


    i dont like get what you talk here..overally this is a work for compiler
    to simplify it in output

    In my case the compiler is my job too!

    btw you think i should defend the things i was talking about -
    i more see its a waste of time if someone dont understand things
    it is for him if he understoods or not, i have not so much time to
    defend obvious things against the people who not care to much to
    understand things

    i would sy like its taking hours repairing a code that is
    good - whou would like to do it?


    generally such time spanding that you got good code and some weird
    people come nad put a bulshit its wrong and expect me to explain this is
    not its not a good time spending imo

    i would rather expect if some will find some 'bug ' in code then he
    first should understand it

    Why bother posting in a public forum if you don't care about people
    understand what you're on about? Do you not want people to engage?

    Then post to alt.test instead.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Chris M. Thomasson@[email protected] to comp.lang.c on Mon Oct 26 14:17:43 2026
    From Newsgroup: comp.lang.c

    On 10/26/2026 2:11 PM, bartc wrote:
    On 26/10/2026 20:32, fir wrote:
    bartc pisze:

    OK, try a simple experiment: convert some code using your 'or'
    keyword to regular C syntax and post it here. Preferably on a real
    example.


    you cant properly convert this or/and groups to c in good way becouse
    there is flaw in c you cannot express all needed combinations
    generally with sole if 's and else's

    as was showed here
    There are a couple of reasons to express it in C:

    * To illustrate exactly how you want the semantics to work, via
      an existing language whose behaviour is well known

    * To highlight the problem areas

    For example:

      if (f1()) {}
      if (f2()) {}
      ...
      if (!f1() && !f2()) {}

    Here f1/f2 are called twice. This means making internal copies or
    setting flags.

    So you call f1 and f2, then call if (!f1() && !f2()) {}. So, that is
    your choice. Not the fault of C, right?



    You'll find, when converting to regular C, that detecting the case of
    all false will mean checking all conditions, but now those will
    contain duplicates. It is hard to cleanly express, which is a bad
    sign as a prospective language feature.


    i dont like get what you talk here..overally this is a work for compiler
    to simplify it in output

    In my case the compiler is my job too!

    btw you think i should defend the things i was talking about -
    i more see its a waste of time if someone dont understand things
    it is for him if he understoods or not, i have not so much time to
    defend obvious things against the people who not care to much to
    understand things

    i would sy like its taking hours repairing a code that is
    good - whou would like to do it?


    generally such time spanding that you got good code and some weird
    people come nad put a bulshit its wrong and expect me to explain this
    is not its not a good time spending imo

    i would rather expect if some will find some 'bug ' in code then he
    first should understand it

    Why bother posting in a public forum if you don't care about people understand what you're on about? Do you not want people to engage?

    Then post to alt.test instead.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From fir@[email protected] to comp.lang.c on Mon Oct 26 22:37:29 2026
    From Newsgroup: comp.lang.c

    bartc pisze:
    On 26/10/2026 20:13, fir wrote:
    bartc pisze:
    On 26/10/2026 19:39, fir wrote:
    bartc pisze:

    1 no divides (by 2 or 3)
    2 divides by 2
    3 divides by 3
    4 divides by 2
    5 no divides (by 2 or 3)
    6 divides by 2
    6 divides by 3
    7 no divides (by 2 or 3)
    8 divides by 2
    9 divides by 3
    10 divides by 2
    11 no divides (by 2 or 3)
    12 divides by 2
    12 divides by 3
    13 no divides (by 2 or 3)
    14 divides by 2
    15 divides by 3
    16 divides by 2
    17 no divides (by 2 or 3)
    18 divides by 2
    18 divides by 3
    19 no divides (by 2 or 3)

    OK, thanks. So the pattern you're talking about is this:

       case (c1) {s1}
       case (c2) {s2}
       case (c3) {s3}
       else      {s4}

    where each of s1/s2/s3 is executed if the corresponding c1/c2/c3 is >>>>> true, independently of the others. At least one statement will be
    executed in 7 of the 8 possible boolean combinations in this example. >>>>>
    s4 is only executed when each of c1/c2/c3 is false. In other words:

       if (c1) {s1}
       if (c2) {s2}
       if (c3) {s3}
       if (!c1 && !c2 && !c3) {s4}

    Assuming c1/c2/c3 are not modified by s1/s2/s3, but this is also
    partly the case with your proposal.

    Or maybe it can be done like this:

       if (c1 || c2 || c3) {
           s4
       else if (c1) {s1)
       ....

    The syntax will anyway need some work to tie all those case/if
    parts together (as s2 for example could contain nested versions).

    Or you can forget about having to create a hard-to-grasp and
    awkward- to-implement feature like this, and either use workarounds >>>>> like my C examples, or use another approach to the problem.



    hahaha

    lol ye use worakarounds instead of simple right solution

    The right solution to what problem? It took multiple posts before you
    even managed to explain how your proposal is supposed to behave.


    well i was surprised how slow you think it is the reason you get
    things slow - and that s why it took multiple posts

    Mainly from you failing to explain? You wrote comments like this:

    "this wouldnt work imo as far as im aware becouse this last else dont
    work on "group'"

    IMO? It either works or it doesn't, and if not, explain why 'or' was not just an alias for 'else'.


    i was already talked on it how many times i need to repeat it you think


    if you personally take it a hundred times you think i need to reperat it
    100 times ?

    else dont work becouse you dont need a group else this is else who woork on
    som elogical expresion on group of ifs


    "a else {}" work on sole a (where a is "if () {}"

    you need else who works on group of ifs tied with thse logicel operators

    ( if() {} or if() {} and if() {} ) else {}

    this else work on group and in case of implementing some things properly
    you need such group else

    instead of else you can also have some other keywords

    i mean of group produce binary logical value then two will
    suffice (than and else) but you evetually also not use logical operators
    and and r but use some more keywords alternatively


    if if if if if all {}
    if if if if if none {} //none works here as this ors and group else


    whats the point of me getteing to those various conclusions - point is
    so called "science"... thiose various conclusion make some deeper view
    on language specifficely on what i call deeper C


    i may say its generally surprising some people dont underrstand many
    things here such bad.. but what people understand is somewhat side
    thing, sine specialised content shallow group of people understoods

    as i said i got no time to explain things you specifically dont
    understand for hours - i can explain it to you by putting one post or
    two but answering if for hours a day is too much



    and i make laugh becouse its funny how some slowly take some things
    and how bad answer thay give - its kinda laughable

    Well, this is the thing: given a well-specified, well-thought-out
    feature, I can probably implement it in one of my compilers within a day.

    That can serve as a proof-of-concept, and can be used to see how well it stands up and how useful it actually is.

    This one wouldn't pass that bar. But also, I've not convinced that you
    put much thought into it. If I implemented it, you'd change your mind
    about it, or add new twists, or get bored and think up something else.

    It would be a waste of time.

    So what's the purpose of these hundreds of wacky, random ideas: do you expect someone else to implement them for you? If so, in which language?

    Today was a bit of fun, but I can't take your ideas seriously.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From fir@[email protected] to comp.lang.c on Mon Oct 26 22:40:43 2026
    From Newsgroup: comp.lang.c

    bartc pisze:
    Today was a bit of fun, but I can't take your ideas seriously.

    definitely was not it was boring and a time waste ..i could do much
    btter things

    escept maybe cooking this example with if {} or if {} else {}
    this example is good as its small and shows the lacks of ifs and elses
    logic in c (so its quite otable example)

    but besides that it was timewaste

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Chris M. Thomasson@[email protected] to comp.lang.c on Mon Oct 26 14:43:02 2026
    From Newsgroup: comp.lang.c

    On 10/26/2026 2:11 PM, bartc wrote:
    On 26/10/2026 20:32, fir wrote:
    bartc pisze:

    OK, try a simple experiment: convert some code using your 'or'
    keyword to regular C syntax and post it here. Preferably on a real
    example.


    you cant properly convert this or/and groups to c in good way becouse
    there is flaw in c you cannot express all needed combinations
    generally with sole if 's and else's

    as was showed here
    There are a couple of reasons to express it in C:

    * To illustrate exactly how you want the semantics to work, via
      an existing language whose behaviour is well known

    * To highlight the problem areas

    For example:

      if (f1()) {}
      if (f2()) {}
      ...




      if (!f1() && !f2()) {}

    Here f1/f2 are called twice. This means making internal copies or
    setting flags.
    Also, if f1 succeeds, then f2 might not have to be called at all because
    it already broke the contract?

    [...]


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Chris M. Thomasson@[email protected] to comp.lang.c on Mon Oct 26 14:46:16 2026
    From Newsgroup: comp.lang.c

    On 10/26/2026 2:40 PM, fir wrote:
    bartc pisze:
    Today was a bit of fun, but I can't take your ideas seriously.

    definitely was not it was boring and a time waste ..i could do much
    btter things

    escept maybe cooking this example with if {} or if {}  else {}
    this example is good as its small and shows the lacks of ifs and elses
    logic in c (so its quite otable example)

    but besides that it was timewaste


    Why are you wasting your time here on comp.lang.c?
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bartc@[email protected] to comp.lang.c on Mon Oct 26 21:50:15 2026
    From Newsgroup: comp.lang.c

    On 26/10/2026 21:17, Chris M. Thomasson wrote:
    On 10/26/2026 2:11 PM, bartc wrote:
    On 26/10/2026 20:32, fir wrote:
    bartc pisze:

    OK, try a simple experiment: convert some code using your 'or'
    keyword to regular C syntax and post it here. Preferably on a real
    example.


    you cant properly convert this or/and groups to c in good way becouse
    there is flaw in c you cannot express all needed combinations
    generally with sole if 's and else's

    as was showed here
    There are a couple of reasons to express it in C:

    * To illustrate exactly how you want the semantics to work, via
       an existing language whose behaviour is well known

    * To highlight the problem areas

    For example:

       if (f1()) {}
       if (f2()) {}
       ...
       if (!f1() && !f2()) {}

    Here f1/f2 are called twice. This means making internal copies or
    setting flags.

    So you call f1 and f2, then call if (!f1() && !f2()) {}. So, that is
    your choice. Not the fault of C, right?

    It's not the fault of C. But the C illustrates the logic of this new
    feature: it must only call the 'else' clause when none of the conditions
    are true.

    But if the most direct way of expressing it has this issue, then extra workarounds are needed, for example:

    flag=1;
    if f1() {flag=0;...)
    if f2() {flag=0;...)
    if (flag) {}

    (Note the logic here is slightly different: the else block is executed
    when none of the previous blocks have been entered. Because conditionals
    may have different values at this point. But we don't know the proper spec.)

    This actually isn't too bad, but in that case, why do we even need this
    new feature?

    My main problem with it is that it is unintuitive and that its use-cases
    are limited. It's also likely to morph into something else when fir gets
    bored with it.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From fir@[email protected] to comp.lang.c on Mon Oct 26 22:51:30 2026
    From Newsgroup: comp.lang.c

    bartc pisze:
    On 26/10/2026 20:13, fir wrote:
    bartc pisze:
    On 26/10/2026 19:39, fir wrote:
    bartc pisze:

    1 no divides (by 2 or 3)
    2 divides by 2
    3 divides by 3
    4 divides by 2
    5 no divides (by 2 or 3)
    6 divides by 2
    6 divides by 3
    7 no divides (by 2 or 3)
    8 divides by 2
    9 divides by 3
    10 divides by 2
    11 no divides (by 2 or 3)
    12 divides by 2
    12 divides by 3
    13 no divides (by 2 or 3)
    14 divides by 2
    15 divides by 3
    16 divides by 2
    17 no divides (by 2 or 3)
    18 divides by 2
    18 divides by 3
    19 no divides (by 2 or 3)

    OK, thanks. So the pattern you're talking about is this:

       case (c1) {s1}
       case (c2) {s2}
       case (c3) {s3}
       else      {s4}

    where each of s1/s2/s3 is executed if the corresponding c1/c2/c3 is >>>>> true, independently of the others. At least one statement will be
    executed in 7 of the 8 possible boolean combinations in this example. >>>>>
    s4 is only executed when each of c1/c2/c3 is false. In other words:

       if (c1) {s1}
       if (c2) {s2}
       if (c3) {s3}
       if (!c1 && !c2 && !c3) {s4}

    Assuming c1/c2/c3 are not modified by s1/s2/s3, but this is also
    partly the case with your proposal.

    Or maybe it can be done like this:

       if (c1 || c2 || c3) {
           s4
       else if (c1) {s1)
       ....

    The syntax will anyway need some work to tie all those case/if
    parts together (as s2 for example could contain nested versions).

    Or you can forget about having to create a hard-to-grasp and
    awkward- to-implement feature like this, and either use workarounds >>>>> like my C examples, or use another approach to the problem.



    hahaha

    lol ye use worakarounds instead of simple right solution

    The right solution to what problem? It took multiple posts before you
    even managed to explain how your proposal is supposed to behave.


    well i was surprised how slow you think it is the reason you get
    things slow - and that s why it took multiple posts

    Mainly from you failing to explain? You wrote comments like this:

    "this wouldnt work imo as far as im aware becouse this last else dont
    work on "group'"

    IMO? It either works or it doesn't, and if not, explain why 'or' was not just an alias for 'else'.

    and i make laugh becouse its funny how some slowly take some things
    and how bad answer thay give - its kinda laughable

    Well, this is the thing: given a well-specified, well-thought-out
    feature, I can probably implement it in one of my compilers within a day.

    That can serve as a proof-of-concept, and can be used to see how well it stands up and how useful it actually is.

    This one wouldn't pass that bar. But also, I've not convinced that you
    put much thought into it. If I implemented it, you'd change your mind
    about it, or add new twists, or get bored and think up something else.

    It would be a waste of time.

    So what's the purpose of these hundreds of wacky, random ideas: do you expect someone else to implement them for you? If so, in which language?

    Today was a bit of fun, but I can't take your ideas seriously.

    implementation is not so much importand..as i said more than once here
    the implementation is far easier that obtaining some of the observations
    and conclusions

    do make some implementation one nedd to do a dose of relatively shallow
    work (not totally as imlementation also has its depth) but to go to
    some conclusion imo needs more deep and open work

    thse ideas are also not random


    for example noticing that if else sytem in c is generally flawed
    is quite notable..i wouldnt say its random idea

    overally c as language some could say is drafted with a hundreds of
    random ideas (in such sense of random)


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bartc@[email protected] to comp.lang.c on Mon Oct 26 21:55:14 2026
    From Newsgroup: comp.lang.c

    On 26/10/2026 21:43, Chris M. Thomasson wrote:
    On 10/26/2026 2:11 PM, bartc wrote:
    On 26/10/2026 20:32, fir wrote:
    bartc pisze:

    OK, try a simple experiment: convert some code using your 'or'
    keyword to regular C syntax and post it here. Preferably on a real
    example.


    you cant properly convert this or/and groups to c in good way becouse
    there is flaw in c you cannot express all needed combinations
    generally with sole if 's and else's

    as was showed here
    There are a couple of reasons to express it in C:

    * To illustrate exactly how you want the semantics to work, via
       an existing language whose behaviour is well known

    * To highlight the problem areas

    For example:

       if (f1()) {}
       if (f2()) {}
       ...




       if (!f1() && !f2()) {}

    Here f1/f2 are called twice. This means making internal copies or
    setting flags.
    Also, if f1 succeeds, then f2 might not have to be called at all because
    it already broke the contract?
    No, the 'if f2(){}' line must be executed whether f1() was true or also.

    As I understand the feature: they are independent conditional blocks.
    But the final else{} must be executed if all were false.

    I think if you have to explain it, then it's a bad sign!
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Chris M. Thomasson@[email protected] to comp.lang.c on Mon Oct 26 15:01:20 2026
    From Newsgroup: comp.lang.c

    On 10/26/2026 2:55 PM, bartc wrote:
    On 26/10/2026 21:43, Chris M. Thomasson wrote:
    On 10/26/2026 2:11 PM, bartc wrote:
    On 26/10/2026 20:32, fir wrote:
    bartc pisze:

    OK, try a simple experiment: convert some code using your 'or'
    keyword to regular C syntax and post it here. Preferably on a real
    example.


    you cant properly convert this or/and groups to c in good way
    becouse there is flaw in c you cannot express all needed
    combinations generally with sole if 's and else's

    as was showed here
    There are a couple of reasons to express it in C:

    * To illustrate exactly how you want the semantics to work, via
       an existing language whose behaviour is well known

    * To highlight the problem areas

    For example:

       if (f1()) {}
       if (f2()) {}
       ...




       if (!f1() && !f2()) {}

    Here f1/f2 are called twice. This means making internal copies or
    setting flags.
    Also, if f1 succeeds, then f2 might not have to be called at all
    because it already broke the contract?
    No, the 'if f2(){}' line must be executed whether f1() was true or also.

    As I understand the feature: they are independent conditional blocks.
    But the final else{} must be executed if all were false.

    I think if you have to explain it, then it's a bad sign!

    Oh shit. I was isolating the following line, not the two previous calls:

    if (!f1() && !f2()) {}
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@[email protected] to comp.lang.c on Mon Oct 26 23:37:30 2026
    From Newsgroup: comp.lang.c

    On 26/10/2026 22:50, bartc wrote:
    On 26/10/2026 21:17, Chris M. Thomasson wrote:
    On 10/26/2026 2:11 PM, bartc wrote:
    On 26/10/2026 20:32, fir wrote:
    bartc pisze:

    OK, try a simple experiment: convert some code using your 'or'
    keyword to regular C syntax and post it here. Preferably on a real
    example.


    you cant properly convert this or/and groups to c in good way
    becouse there is flaw in c you cannot express all needed
    combinations generally with sole if 's and else's

    as was showed here
    There are a couple of reasons to express it in C:

    * To illustrate exactly how you want the semantics to work, via
       an existing language whose behaviour is well known

    * To highlight the problem areas

    For example:

       if (f1()) {}
       if (f2()) {}
       ...
       if (!f1() && !f2()) {}

    Here f1/f2 are called twice. This means making internal copies or
    setting flags.

    So you call f1 and f2, then call if (!f1() && !f2()) {}. So, that is
    your choice. Not the fault of C, right?

    It's not the fault of C. But the C illustrates the logic of this new feature: it must only call the 'else' clause when none of the conditions
    are true.

    But if the most direct way of expressing it has this issue, then extra workarounds are needed, for example:

       flag=1;
       if f1() {flag=0;...)
       if f2() {flag=0;...)
       if (flag) {}

    (Note the logic here is slightly different: the else block is executed
    when none of the previous blocks have been entered. Because conditionals
    may have different values at this point. But we don't know the proper
    spec.)

    This actually isn't too bad, but in that case, why do we even need this
    new feature?

    My main problem with it is that it is unintuitive and that its use-cases
    are limited. It's also likely to morph into something else when fir gets bored with it.



    #define fir_switch _Bool flag = 1; {
    #define or_if(...) } if (__VA_ARGS__) { flag = 0;
    #define otherwise } if (!flag)

    Then Fir can write :

    fir_switch
    or_if (x % 2 == 0) printf("\n divides by 2");
    or_if (x % 3 == 0) printf("\n divides by 3");
    otherwise printf("\n does not divide by 2 or 3");

    I haven't tested the defines, and I think it is a terrible idea (it
    should at least be called "and_if"), but it comes very close to the
    syntax and semantics Fir appears to want.



    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From fir@[email protected] to comp.lang.c on Tue Oct 27 00:01:54 2026
    From Newsgroup: comp.lang.c

    David Brown pisze:
    On 26/10/2026 22:50, bartc wrote:
    On 26/10/2026 21:17, Chris M. Thomasson wrote:
    On 10/26/2026 2:11 PM, bartc wrote:
    On 26/10/2026 20:32, fir wrote:
    bartc pisze:

    OK, try a simple experiment: convert some code using your 'or'
    keyword to regular C syntax and post it here. Preferably on a real >>>>>> example.


    you cant properly convert this or/and groups to c in good way
    becouse there is flaw in c you cannot express all needed
    combinations generally with sole if 's and else's

    as was showed here
    There are a couple of reasons to express it in C:

    * To illustrate exactly how you want the semantics to work, via
       an existing language whose behaviour is well known

    * To highlight the problem areas

    For example:

       if (f1()) {}
       if (f2()) {}
       ...
       if (!f1() && !f2()) {}

    Here f1/f2 are called twice. This means making internal copies or
    setting flags.

    So you call f1 and f2, then call if (!f1() && !f2()) {}. So, that is
    your choice. Not the fault of C, right?

    It's not the fault of C. But the C illustrates the logic of this new
    feature: it must only call the 'else' clause when none of the
    conditions are true.

    But if the most direct way of expressing it has this issue, then extra
    workarounds are needed, for example:

        flag=1;
        if f1() {flag=0;...)
        if f2() {flag=0;...)
        if (flag) {}

    (Note the logic here is slightly different: the else block is executed
    when none of the previous blocks have been entered. Because
    conditionals may have different values at this point. But we don't
    know the proper spec.)

    This actually isn't too bad, but in that case, why do we even need
    this new feature?

    My main problem with it is that it is unintuitive and that its
    use-cases are limited. It's also likely to morph into something else
    when fir gets bored with it.



    #define fir_switch _Bool flag = 1; {
    #define or_if(...) } if (__VA_ARGS__) { flag = 0;
    #define otherwise } if (!flag)

    Then Fir can write :

        fir_switch
        or_if (x % 2 == 0) printf("\n divides by 2");
        or_if (x % 3 == 0) printf("\n divides by 3");
        otherwise printf("\n does not divide by 2 or 3");

    I haven't tested the defines, and I think it is a terrible idea (it
    should at least be called "and_if"), but it comes very close to the
    syntax and semantics Fir appears to want.



    totally no, its not also i want this i just makec conclusion if-else
    system is flawed

    you may ment it on some ways lik

    if {}
    or
    if {}
    else {}

    or

    case {}
    case {}
    otherwise {}

    in first case you got heneral system of logic operators applied to group
    of ifs (coz you may use not olny or but also and or not etc),

    in second you got like predefined keywords for "or or or" case
    (here in fact otherwise keyword means use or for cases and of 0
    evaluate otherwise)

    i thing you will nned a general but predefined may be also handy so
    eventually language could implement both (such as it has many forms for
    loops to increase intentions readability)


    flag is a nonsense its liek implementing else with flag

    int not = 1;

    if (a>2) {not =0; //...}
    if(not) {}

    ;C

    NOTE btw this case not only shows flaw in if rlse system but is just
    natural fom of switch (both of them i mean "if or if else" and "case
    case otherwise"..and imo thsi form is better than switch as its more
    natural its grounded -its also shows lacks of switch so it shows both
    if-else system is flawed and switch is flawed too



    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From fir@[email protected] to comp.lang.c on Tue Oct 27 00:28:33 2026
    From Newsgroup: comp.lang.c

    fir pisze:
    David Brown pisze:
    On 26/10/2026 22:50, bartc wrote:
    On 26/10/2026 21:17, Chris M. Thomasson wrote:
    On 10/26/2026 2:11 PM, bartc wrote:
    On 26/10/2026 20:32, fir wrote:
    bartc pisze:

    OK, try a simple experiment: convert some code using your 'or'
    keyword to regular C syntax and post it here. Preferably on a
    real example.


    you cant properly convert this or/and groups to c in good way
    becouse there is flaw in c you cannot express all needed
    combinations generally with sole if 's and else's

    as was showed here
    There are a couple of reasons to express it in C:

    * To illustrate exactly how you want the semantics to work, via
       an existing language whose behaviour is well known

    * To highlight the problem areas

    For example:

       if (f1()) {}
       if (f2()) {}
       ...
       if (!f1() && !f2()) {}

    Here f1/f2 are called twice. This means making internal copies or
    setting flags.

    So you call f1 and f2, then call if (!f1() && !f2()) {}. So, that is
    your choice. Not the fault of C, right?

    It's not the fault of C. But the C illustrates the logic of this new
    feature: it must only call the 'else' clause when none of the
    conditions are true.

    But if the most direct way of expressing it has this issue, then
    extra workarounds are needed, for example:

        flag=1;
        if f1() {flag=0;...)
        if f2() {flag=0;...)
        if (flag) {}

    (Note the logic here is slightly different: the else block is
    executed when none of the previous blocks have been entered. Because
    conditionals may have different values at this point. But we don't
    know the proper spec.)

    This actually isn't too bad, but in that case, why do we even need
    this new feature?

    My main problem with it is that it is unintuitive and that its
    use-cases are limited. It's also likely to morph into something else
    when fir gets bored with it.



    #define fir_switch _Bool flag = 1; {
    #define or_if(...) } if (__VA_ARGS__) { flag = 0;
    #define otherwise } if (!flag)

    Then Fir can write :

         fir_switch
         or_if (x % 2 == 0) printf("\n divides by 2");
         or_if (x % 3 == 0) printf("\n divides by 3");
         otherwise printf("\n does not divide by 2 or 3");

    I haven't tested the defines, and I think it is a terrible idea (it
    should at least be called "and_if"), but it comes very close to the
    syntax and semantics Fir appears to want.



    totally no, its not also i want this i just makec conclusion if-else
    system is flawed

    you may ment it on some ways lik

    if {}
    or
    if {}
    else {}

    or

    case {}
    case {}
    otherwise {}

    in first case you got heneral system of logic operators applied to group
    of ifs (coz you may use not olny or but also and or not etc),

     in second you got like predefined keywords for "or or or" case
    (here in fact otherwise keyword means use or for cases and of 0
    evaluate otherwise)

    i thing you will nned a general but predefined may be also handy so eventually language could implement both (such as it has many forms for loops to increase intentions readability)


    flag is a nonsense its liek implementing else with flag

    int not = 1;

    if (a>2) {not =0; //...}
    if(not) {}

    ;C

    NOTE btw this case not only shows flaw in if rlse system but is just
    natural fom of switch (both of them i mean "if or if else" and "case
    case otherwise"..and imo thsi form is better than switch as its more
    natural its grounded -its also shows lacks of switch so it shows both
    if-else system is flawed and switch is flawed too



    overally switch in c imo is in fact quite like goto not like if

    but even if so its not general as it should bcouse if so then you should
    also be jumping back


    switch n //goto 1 2 3 if other goto default

    case 1:
    case 2:
    case 4:
    default:


    //if so it should allow amany switches and jumps back


    int s =1;

    case 2:

    switch s

    case 1:
    int b =2
    case 3:
    case 4:

    switch b

    case 5:

    such switch i would more like as its much ore logical and right

    but if so switch sjould be eventually named goto
    (eventually goto() to make difference withh jumping under labe a and
    value of (a) (though it also may staj switch for illustration here) and
    case may be removed, defaul should be ranemed by other which more fits
    the meaning


    foo()
    {
    int s =1;

    2:

    switch s

    1:
    int b =2
    3:
    4:

    switch b

    other:

    }


    it illustrates soe things, like this c swich syntax should be

    switch s;

    1:
    2:
    3:
    other:

    break is not a part of it indeed it just is to make jump outside a block
    *could eventually be also continue

    if so some could at block at free will

    switch s;
    1: {2:
    3: break;
    other: continue; }


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From fir@[email protected] to comp.lang.c on Tue Oct 27 00:55:13 2026
    From Newsgroup: comp.lang.c

    fir pisze:
    David Brown pisze:
    On 26/10/2026 22:50, bartc wrote:
    On 26/10/2026 21:17, Chris M. Thomasson wrote:
    On 10/26/2026 2:11 PM, bartc wrote:
    On 26/10/2026 20:32, fir wrote:
    bartc pisze:

    OK, try a simple experiment: convert some code using your 'or'
    keyword to regular C syntax and post it here. Preferably on a
    real example.


    you cant properly convert this or/and groups to c in good way
    becouse there is flaw in c you cannot express all needed
    combinations generally with sole if 's and else's

    as was showed here
    There are a couple of reasons to express it in C:

    * To illustrate exactly how you want the semantics to work, via
       an existing language whose behaviour is well known

    * To highlight the problem areas

    For example:

       if (f1()) {}
       if (f2()) {}
       ...
       if (!f1() && !f2()) {}

    Here f1/f2 are called twice. This means making internal copies or
    setting flags.

    So you call f1 and f2, then call if (!f1() && !f2()) {}. So, that is
    your choice. Not the fault of C, right?

    It's not the fault of C. But the C illustrates the logic of this new
    feature: it must only call the 'else' clause when none of the
    conditions are true.

    But if the most direct way of expressing it has this issue, then
    extra workarounds are needed, for example:

        flag=1;
        if f1() {flag=0;...)
        if f2() {flag=0;...)
        if (flag) {}

    (Note the logic here is slightly different: the else block is
    executed when none of the previous blocks have been entered. Because
    conditionals may have different values at this point. But we don't
    know the proper spec.)

    This actually isn't too bad, but in that case, why do we even need
    this new feature?

    My main problem with it is that it is unintuitive and that its
    use-cases are limited. It's also likely to morph into something else
    when fir gets bored with it.



    #define fir_switch _Bool flag = 1; {
    #define or_if(...) } if (__VA_ARGS__) { flag = 0;
    #define otherwise } if (!flag)

    Then Fir can write :

         fir_switch
         or_if (x % 2 == 0) printf("\n divides by 2");
         or_if (x % 3 == 0) printf("\n divides by 3");
         otherwise printf("\n does not divide by 2 or 3");

    I haven't tested the defines, and I think it is a terrible idea (it
    should at least be called "and_if"), but it comes very close to the
    syntax and semantics Fir appears to want.



    totally no, its not also i want this i just makec conclusion if-else
    system is flawed

    you may ment it on some ways lik

    if {}
    or
    if {}
    else {}

    or

    case {}
    case {}
    otherwise {}

    in first case you got heneral system of logic operators applied to group
    of ifs (coz you may use not olny or but also and or not etc),

     in second you got like predefined keywords for "or or or" case
    (here in fact otherwise keyword means use or for cases and of 0
    evaluate otherwise)

    i thing you will nned a general but predefined may be also handy so eventually language could implement both (such as it has many forms for loops to increase intentions readability)


    flag is a nonsense its liek implementing else with flag

    int not = 1;

    if (a>2) {not =0; //...}
    if(not) {}

    ;C

    NOTE btw this case not only shows flaw in if rlse system but is just
    natural fom of switch (both of them i mean "if or if else" and "case
    case otherwise"..and imo thsi form is better than switch as its more
    natural its grounded -its also shows lacks of switch so it shows both
    if-else system is flawed and switch is flawed too



    btw example for and


    if(x>0) printf("right"); and if(x<w) printf("left"); else printf("
    outside");


    this if im not wrong will print

    "right"
    "right outside"
    "left"
    "left outside"
    "right left"

    if im not wrong also this you will not whow with normal if elses
    of witch c switch wiyhout more complex code


    (i not checked it though)


    if so it just shows that small additions of or and and genarating that usecases justify those additions and its omitions are kinda flaw in if
    else system

    you may rarely need that but there are cases when you may need that
    so the lack of it its arrtificial (as if-else is not complete)
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bartc@[email protected] to comp.lang.c on Tue Oct 27 01:12:54 2026
    From Newsgroup: comp.lang.c

    On 26/10/2026 22:37, David Brown wrote:
    On 26/10/2026 22:50, bartc wrote:
    On 26/10/2026 21:17, Chris M. Thomasson wrote:
    On 10/26/2026 2:11 PM, bartc wrote:
    On 26/10/2026 20:32, fir wrote:
    bartc pisze:

    OK, try a simple experiment: convert some code using your 'or'
    keyword to regular C syntax and post it here. Preferably on a real >>>>>> example.


    you cant properly convert this or/and groups to c in good way
    becouse there is flaw in c you cannot express all needed
    combinations generally with sole if 's and else's

    as was showed here
    There are a couple of reasons to express it in C:

    * To illustrate exactly how you want the semantics to work, via
       an existing language whose behaviour is well known

    * To highlight the problem areas

    For example:

       if (f1()) {}
       if (f2()) {}
       ...
       if (!f1() && !f2()) {}

    Here f1/f2 are called twice. This means making internal copies or
    setting flags.

    So you call f1 and f2, then call if (!f1() && !f2()) {}. So, that is
    your choice. Not the fault of C, right?

    It's not the fault of C. But the C illustrates the logic of this new
    feature: it must only call the 'else' clause when none of the
    conditions are true.

    But if the most direct way of expressing it has this issue, then extra
    workarounds are needed, for example:

        flag=1;
        if f1() {flag=0;...)
        if f2() {flag=0;...)
        if (flag) {}

    (Note the logic here is slightly different: the else block is executed
    when none of the previous blocks have been entered. Because
    conditionals may have different values at this point. But we don't
    know the proper spec.)

    This actually isn't too bad, but in that case, why do we even need
    this new feature?

    My main problem with it is that it is unintuitive and that its use-
    cases are limited. It's also likely to morph into something else when
    fir gets bored with it.



    #define fir_switch _Bool flag = 1; {
    #define or_if(...) } if (__VA_ARGS__) { flag = 0;
    #define otherwise } if (!flag)

    Then Fir can write :

        fir_switch
        or_if (x % 2 == 0) printf("\n divides by 2");
        or_if (x % 3 == 0) printf("\n divides by 3");
        otherwise printf("\n does not divide by 2 or 3");

    I haven't tested the defines, and I think it is a terrible idea (it
    should at least be called "and_if"), but it comes very close to the
    syntax and semantics Fir appears to want.
    It looks pretty good and it seems to work (the !flag needs the reverse
    logic). The 'and_if' makes more sense too.

    But of course it's not good enough for fir; there's always something.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Chris M. Thomasson@[email protected] to comp.lang.c on Mon Oct 26 18:43:02 2026
    From Newsgroup: comp.lang.c

    On 10/26/2026 6:12 PM, bartc wrote:
    On 26/10/2026 22:37, David Brown wrote:
    On 26/10/2026 22:50, bartc wrote:
    On 26/10/2026 21:17, Chris M. Thomasson wrote:
    On 10/26/2026 2:11 PM, bartc wrote:
    On 26/10/2026 20:32, fir wrote:
    bartc pisze:

    OK, try a simple experiment: convert some code using your 'or'
    keyword to regular C syntax and post it here. Preferably on a
    real example.


    you cant properly convert this or/and groups to c in good way
    becouse there is flaw in c you cannot express all needed
    combinations generally with sole if 's and else's

    as was showed here
    There are a couple of reasons to express it in C:

    * To illustrate exactly how you want the semantics to work, via
       an existing language whose behaviour is well known

    * To highlight the problem areas

    For example:

       if (f1()) {}
       if (f2()) {}
       ...
       if (!f1() && !f2()) {}

    Here f1/f2 are called twice. This means making internal copies or
    setting flags.

    So you call f1 and f2, then call if (!f1() && !f2()) {}. So, that is
    your choice. Not the fault of C, right?

    It's not the fault of C. But the C illustrates the logic of this new
    feature: it must only call the 'else' clause when none of the
    conditions are true.

    But if the most direct way of expressing it has this issue, then
    extra workarounds are needed, for example:

        flag=1;
        if f1() {flag=0;...)
        if f2() {flag=0;...)
        if (flag) {}

    (Note the logic here is slightly different: the else block is
    executed when none of the previous blocks have been entered. Because
    conditionals may have different values at this point. But we don't
    know the proper spec.)

    This actually isn't too bad, but in that case, why do we even need
    this new feature?

    My main problem with it is that it is unintuitive and that its use-
    cases are limited. It's also likely to morph into something else when
    fir gets bored with it.



    #define fir_switch _Bool flag = 1; {
    #define or_if(...) } if (__VA_ARGS__) { flag = 0;
    #define otherwise } if (!flag)

    Then Fir can write :

         fir_switch
         or_if (x % 2 == 0) printf("\n divides by 2");
         or_if (x % 3 == 0) printf("\n divides by 3");
         otherwise printf("\n does not divide by 2 or 3");

    I haven't tested the defines, and I think it is a terrible idea (it
    should at least be called "and_if"), but it comes very close to the
    syntax and semantics Fir appears to want.
    It looks pretty good and it seems to work (the !flag needs the reverse logic). The 'and_if' makes more sense too.

    But of course it's not good enough for fir; there's always something.

    The never ending story?

    https://youtu.be/lHytjEj7B9g?list=RDlHytjEj7B9g
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Chris M. Thomasson@[email protected] to comp.lang.c on Mon Oct 26 18:47:28 2026
    From Newsgroup: comp.lang.c

    On 10/6/2026 4:05 PM, Chris M. Thomasson wrote:
    On 10/5/2026 4:11 PM, bart wrote:
    On 05/10/2026 22:48, Kaz Kylheku wrote:
    On 2026-10-05, bart <[email protected]> wrote:
    A lot of what big compilers do is what used to be called 'linting'.

    I don't suspect you can get rid of that in any language.

    The reason is that as experience with the given language grows, it is
    found that programmers make certain mistakes, where making formal
    syntactic and semantic rules against those mistakes, and sticking
    them into the language, would be a poor idea.

    At some point, you are trying to design a pencil that cannot be
    used to draw an optical illusion.

    I don't consider that to be their job, which should be to verify my
    program and turn it into runnable code, and not give opinions.

    That's a waste of potential; why would you refuse a machine that
    can apply hundreds of deterministic pattern matching rules against
    possible trouble situations in hundreds of thousands of lines of code,
    in seconds.

    I simply don't care about it. I don't have seconds to waste either.

    Why not?

    [...]



    Ask you boss, tell them I have some interesting ideas, they know you
    might have had a drink or two. Show them your code. See what happens!
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Chris M. Thomasson@[email protected] to comp.lang.c on Mon Oct 26 18:48:00 2026
    From Newsgroup: comp.lang.c

    On 10/7/2026 3:31 PM, bart wrote:
    On 07/10/2026 22:06, Chris M. Thomasson wrote:
    On 10/7/2026 5:52 AM, bart wrote:
    On 07/10/2026 01:42, Kaz Kylheku wrote:
    On 2026-10-05, bart <[email protected]> wrote:
    On 05/10/2026 22:48, Kaz Kylheku wrote:
    On 2026-10-05, bart <[email protected]> wrote:
    A lot of what big compilers do is what used to be called 'linting'. >>>>>>
    I don't suspect you can get rid of that in any language.

    The reason is that as experience with the given language grows, it is >>>>>> found that programmers make certain mistakes, where making formal
    syntactic and semantic rules against those mistakes, and sticking
    them into the language, would be a poor idea.

    At some point, you are trying to design a pencil that cannot be
    used to draw an optical illusion.

    I don't consider that to be their job, which should be to verify my >>>>>>> program and turn it into runnable code, and not give opinions.

    That's a waste of potential; why would you refuse a machine that
    can apply hundreds of deterministic pattern matching rules against >>>>>> possible trouble situations in hundreds of thousands of lines of
    code,
    in seconds.

    I simply don't care about it. I don't have seconds to waste either.

    Your implementation of the same thing would take milliseconds, of
    course.

    I wouldn't want it at all.

    But if I had to implement it, I don't know how long it would take. If
    I found that it was taking disproportionately long (compared to the
    main task of generating a binary), then I would separate it out from
    the compiler, as I've suggested.

    For example, if 90% of compile-time was spent on it.


    Here are some common C-compiling scenarios:

    * You want to build a finished, working, debugged program from source. >>>>>     This does need the compiler spending time double-guessing the >>>>> author's
        intentions, and in any case the person building it is not going to >>>>>     mess with the source

    * You are building a program which is machine-transpiled C code. It
        should be valid C with no errors. (If there are, that is the
        responsibility of the transpiler author.) But again you don't care >>>>>     about style, or the fact that there are lots of unused labels for >>>>>     example (common in such code)

    Then

    * you still want linting in the source language.

    Possibly. I don't care too much about that either. In my stuff, I do
    very little in the way of advisory reports, which are only enabled
    infrequently.

    But the context here is using linting to warn about things that are a
    consequence of C's design, such as switch 'break' that is the subject
    of the thread.

    I prefer to deal with that with a better language design.

    Are you making a "new" C?[...]

    I'm not making anything.

    Why go after C... Make something better?




    I have long maintained a personal systems language which fixes most of
    my moans about C (and even deals with some of fir's needs, but those
    seem to change erratically).

    It would have been good for /someone else/ to have evolved C in a
    direction I'd have found useful, but current evolvement of C is not interesting to me and IMO misguided.

    Since I have my own solutions for the little coding I do now, this
    doesn't matter so much - let C aficionados be masochists if they want.

    But I am still interested in tooling (which has its own masochists!).

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Chris M. Thomasson@[email protected] to comp.lang.c on Mon Oct 26 20:53:59 2026
    From Newsgroup: comp.lang.c

    On 10/7/2026 1:35 AM, David Brown wrote:
    On 07/10/2026 01:45, Lawrence D’Oliveiro wrote:
    On Tue, 6 Oct 2026 16:08:25 -0700, Chris M. Thomasson wrote:

    On 10/6/2026 3:41 AM, David Brown wrote:

    Anyone who sometimes makes mistakes should enable warnings.  And
    that means /everyone/ should enable copious warnings.

    Coin that!

    Then there is “confirmation fatigue”, where you get too inured to
    ignoring spurious warnings, and miss the important one(s) in among the
    noise.

    Enabling lots of warning options does not mean triggering lots of warnings!


    I don’t think there is any idiot-proof way to avoid being an idiot ...


    Excellent.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From fir@[email protected] to comp.lang.c on Tue Oct 27 09:37:34 2026
    From Newsgroup: comp.lang.c

    bartc pisze:
    On 26/10/2026 22:37, David Brown wrote:
    On 26/10/2026 22:50, bartc wrote:
    On 26/10/2026 21:17, Chris M. Thomasson wrote:
    On 10/26/2026 2:11 PM, bartc wrote:
    On 26/10/2026 20:32, fir wrote:
    bartc pisze:

    OK, try a simple experiment: convert some code using your 'or'
    keyword to regular C syntax and post it here. Preferably on a
    real example.


    you cant properly convert this or/and groups to c in good way
    becouse there is flaw in c you cannot express all needed
    combinations generally with sole if 's and else's

    as was showed here
    There are a couple of reasons to express it in C:

    * To illustrate exactly how you want the semantics to work, via
       an existing language whose behaviour is well known

    * To highlight the problem areas

    For example:

       if (f1()) {}
       if (f2()) {}
       ...
       if (!f1() && !f2()) {}

    Here f1/f2 are called twice. This means making internal copies or
    setting flags.

    So you call f1 and f2, then call if (!f1() && !f2()) {}. So, that is
    your choice. Not the fault of C, right?

    It's not the fault of C. But the C illustrates the logic of this new
    feature: it must only call the 'else' clause when none of the
    conditions are true.

    But if the most direct way of expressing it has this issue, then
    extra workarounds are needed, for example:

        flag=1;
        if f1() {flag=0;...)
        if f2() {flag=0;...)
        if (flag) {}

    (Note the logic here is slightly different: the else block is
    executed when none of the previous blocks have been entered. Because
    conditionals may have different values at this point. But we don't
    know the proper spec.)

    This actually isn't too bad, but in that case, why do we even need
    this new feature?

    My main problem with it is that it is unintuitive and that its use-
    cases are limited. It's also likely to morph into something else when
    fir gets bored with it.



    #define fir_switch _Bool flag = 1; {
    #define or_if(...) } if (__VA_ARGS__) { flag = 0;
    #define otherwise } if (!flag)

    Then Fir can write :

         fir_switch
         or_if (x % 2 == 0) printf("\n divides by 2");
         or_if (x % 3 == 0) printf("\n divides by 3");
         otherwise printf("\n does not divide by 2 or 3");

    I haven't tested the defines, and I think it is a terrible idea (it
    should at least be called "and_if"), but it comes very close to the
    syntax and semantics Fir appears to want.
    It looks pretty good and it seems to work (the !flag needs the reverse logic). The 'and_if' makes more sense too.

    But of course it's not good enough for fir; there's always something.

    blame the scienco fo doing just like tat

    (one solution is a solution untill you find better one) ..im just doing science here so its science to blame, i got no problem with that
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From fir@[email protected] to comp.lang.c on Tue Oct 27 09:50:04 2026
    From Newsgroup: comp.lang.c

    fir pisze:
    if(x>0) printf("right"); and if(x<w) printf("left"); else printf(" outside");

    this shows bytw one thing

    such things as

    if(x>0 and x<w) inside() else outside()


    are limited becouse this reduces whole expresion in clase to one binary


    so if you use such conventions as


    if(x>0) and if(x<w)

    of

    if(x>0, x<w)

    you gave more options to define predefined keywords like all/none/some/one


    or even some my write its own function though as the function also
    reduces it is then not possible in such case to do

    if(x>0, x<w) all {} none {} some {}

    it is add more branches at once






    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From fir@[email protected] to comp.lang.c on Tue Oct 27 11:51:01 2026
    From Newsgroup: comp.lang.c

    Chris M. Thomasson pisze:
    On 10/26/2026 2:40 PM, fir wrote:
    bartc pisze:
    Today was a bit of fun, but I can't take your ideas seriously.

    definitely was not it was boring and a time waste ..i could do much
    btter things

    escept maybe cooking this example with if {} or if {}  else {}
    this example is good as its small and shows the lacks of ifs and elses
    logic in c (so its quite otable example)

    but besides that it was timewaste



    maybe to say - general discussion activity on clc is not a timewaste its quality time (sorta)


    the waste is if someone dwells into a false things about things and you
    not talk abour real things but false things and soeme here
    can fund you such ride

    then its a timewaste



    Why are you wasting your time here on comp.lang.c?

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bartc@[email protected] to comp.lang.c on Tue Oct 27 11:51:37 2026
    From Newsgroup: comp.lang.c

    On 27/10/2026 08:37, fir wrote:
    bartc pisze:
    On 26/10/2026 22:37, David Brown wrote:

    #define fir_switch _Bool flag = 1; {
    #define or_if(...) } if (__VA_ARGS__) { flag = 0;
    #define otherwise } if (!flag)

    Then Fir can write :

         fir_switch
         or_if (x % 2 == 0) printf("\n divides by 2");
         or_if (x % 3 == 0) printf("\n divides by 3");
         otherwise printf("\n does not divide by 2 or 3");

    I haven't tested the defines, and I think it is a terrible idea (it
    should at least be called "and_if"), but it comes very close to the
    syntax and semantics Fir appears to want.
    It looks pretty good and it seems to work (the !flag needs the reverse
    logic). The 'and_if' makes more sense too.

    But of course it's not good enough for fir; there's always something.

    blame the scienco fo doing just like tat

    (one solution is a solution untill you find better one) ..im just doing science here so its science to blame, i got no problem with that

    I've no idea what you mean. And I've no idea what it is you're actually
    after. I doubt anyone has. I doubt /you/ do!

    You suggest some new statement type, in a C language forum, somebody
    shows how to implement it in standard C, but your response is:

    "blame the scienco fo doing just like tat"

    Not:

    "Wow, thanks! That's perfect."

    My guess is that you're not interested in actual solutions. You're just thinking up one random idea after another. You don't care for anyone
    else's opinion or input.

    So again, why bother posting here?

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From fir@[email protected] to comp.lang.c on Tue Oct 27 12:57:30 2026
    From Newsgroup: comp.lang.c

    bartc pisze:
    On 27/10/2026 08:37, fir wrote:
    bartc pisze:
    On 26/10/2026 22:37, David Brown wrote:

    #define fir_switch _Bool flag = 1; {
    #define or_if(...) } if (__VA_ARGS__) { flag = 0;
    #define otherwise } if (!flag)

    Then Fir can write :

         fir_switch
         or_if (x % 2 == 0) printf("\n divides by 2");
         or_if (x % 3 == 0) printf("\n divides by 3");
         otherwise printf("\n does not divide by 2 or 3");

    I haven't tested the defines, and I think it is a terrible idea (it
    should at least be called "and_if"), but it comes very close to the
    syntax and semantics Fir appears to want.
    It looks pretty good and it seems to work (the !flag needs the
    reverse logic). The 'and_if' makes more sense too.

    But of course it's not good enough for fir; there's always something.

    blame the scienco fo doing just like tat

    (one solution is a solution untill you find better one) ..im just
    doing science here so its science to blame, i got no problem with that

    I've no idea what you mean. And I've no idea what it is you're actually after. I doubt anyone has. I doubt /you/ do!

    You suggest some new statement type, in a C language forum, somebody
    shows how to implement it in standard C, but your response is:

      "blame the scienco fo doing just like tat"

    Not:

     "Wow, thanks! That's perfect."

    My guess is that you're not interested in actual solutions. You're just thinking up one random idea after another. You don't care for anyone
    else's opinion or input.

    as to ideas I got an idea. Is your goal to stir up trouble here

    coz what yu say is like that and this is making bad content here


    science does that science is finding a solution then it finds another
    solution so you may blame science and say you got idea what science is actually after


    im just doin science - come to some conclusions than after that come to another conclusion...

    why your should problems with science should interest me? im here for
    doin science not to analyse personal problems of clc users


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From fir@[email protected] to comp.lang.c on Tue Oct 27 13:10:26 2026
    From Newsgroup: comp.lang.c

    fir pisze:
    bartc pisze:
    On 27/10/2026 08:37, fir wrote:
    bartc pisze:
    On 26/10/2026 22:37, David Brown wrote:

    #define fir_switch _Bool flag = 1; {
    #define or_if(...) } if (__VA_ARGS__) { flag = 0;
    #define otherwise } if (!flag)

    Then Fir can write :

         fir_switch
         or_if (x % 2 == 0) printf("\n divides by 2");
         or_if (x % 3 == 0) printf("\n divides by 3");
         otherwise printf("\n does not divide by 2 or 3");

    I haven't tested the defines, and I think it is a terrible idea (it >>>>> should at least be called "and_if"), but it comes very close to the >>>>> syntax and semantics Fir appears to want.
    It looks pretty good and it seems to work (the !flag needs the
    reverse logic). The 'and_if' makes more sense too.

    But of course it's not good enough for fir; there's always something.

    blame the scienco fo doing just like tat

    (one solution is a solution untill you find better one) ..im just
    doing science here so its science to blame, i got no problem with that

    I've no idea what you mean. And I've no idea what it is you're
    actually after. I doubt anyone has. I doubt /you/ do!

    You suggest some new statement type, in a C language forum, somebody
    shows how to implement it in standard C, but your response is:

       "blame the scienco fo doing just like tat"

    Not:

      "Wow, thanks! That's perfect."

    My guess is that you're not interested in actual solutions. You're
    just thinking up one random idea after another. You don't care for
    anyone else's opinion or input.

    as to ideas I got an idea. Is your goal to stir up trouble here


    im not tsure as this translation - in polish it is "robić piane" (make
    foam), "bić piane" (it is making nonsense fights/tryin to make nonsense fights/rumbles) like some drunkyard in a bar

    generalli is like i say sin 90 degrees is 1 and some come say "i dont understand it!" "i sucpect your goal is bla bla bla" "i dont know what
    youre after" ..."you say that but later you get bored and will go say something other!"

    its kinda limitedly preposterous and funny but if it consumes hours its timewaste and making useles foam (over wuite scientific statements here )

    youre like more interesting to make foam instead of core topics -
    a bit of foam is not always something totally bad (depends) but
    if it takes hours i become pity for hours wasted where i could generate
    models or write some procedures or just rest



    coz what yu say is like that and this is making bad content here


    science does that science is finding a solution then it finds another solution so you may blame science and say you got idea what science is actually after


    im just doin science - come to some conclusions than after that come to another conclusion...

    why your should problems with science should interest me? im here for
    doin science not to analyse personal problems of clc users



    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bartc@[email protected] to comp.lang.c on Tue Oct 27 12:14:50 2026
    From Newsgroup: comp.lang.c

    On 27/10/2026 11:57, fir wrote:
    bartc pisze:
    On 27/10/2026 08:37, fir wrote:

    blame the scienco fo doing just like tat

    (one solution is a solution untill you find better one) ..im just
    doing science here so its science to blame, i got no problem with that

    I've no idea what you mean. And I've no idea what it is you're
    actually after. I doubt anyone has. I doubt /you/ do!

    You suggest some new statement type, in a C language forum, somebody
    shows how to implement it in standard C, but your response is:

       "blame the scienco fo doing just like tat"

    Not:

      "Wow, thanks! That's perfect."

    My guess is that you're not interested in actual solutions. You're
    just thinking up one random idea after another. You don't care for
    anyone else's opinion or input.


    coz what yu say is like that and this is making bad content here


    science does that science is finding a solution then it finds another solution so you may blame science and say you got idea what science is actually after


    im just doin science - come to some conclusions than after that come to another conclusion...

    why your should problems with science should interest me? im here for
    doin science not to analyse personal problems of clc usersYour 'science' seems to be writing mostly meaningless drivel and then
    posting reams of it in comp.lang.c as though it was your personal blog.

    You don't seem to expect any feedback either, and tend to attack people
    who offer opinions or try to make sense of some of your ideas.

    I should have known from past experience that that never ends well.
    'There's always something'.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From fir@[email protected] to comp.lang.c on Tue Oct 27 13:22:40 2026
    From Newsgroup: comp.lang.c

    bartc pisze:
    On 27/10/2026 11:57, fir wrote:
    bartc pisze:
    On 27/10/2026 08:37, fir wrote:

    blame the scienco fo doing just like tat

    (one solution is a solution untill you find better one) ..im just
    doing science here so its science to blame, i got no problem with that

    I've no idea what you mean. And I've no idea what it is you're
    actually after. I doubt anyone has. I doubt /you/ do!

    You suggest some new statement type, in a C language forum, somebody
    shows how to implement it in standard C, but your response is:

       "blame the scienco fo doing just like tat"

    Not:

      "Wow, thanks! That's perfect."

    My guess is that you're not interested in actual solutions. You're
    just thinking up one random idea after another. You don't care for
    anyone else's opinion or input.


    coz what yu say is like that and this is making bad content here


    science does that science is finding a solution then it finds another
    solution so you may blame science and say you got idea what science is
    actually after


    im just doin science - come to some conclusions than after that come
    to another conclusion...

    why your should problems with science should interest me? im here for
    doin science not to analyse personal problems of clc usersYour
    'science' seems to be writing mostly meaningless drivel and then
    posting reams of it in comp.lang.c as though it was your personal blog.

    You don't seem to expect any feedback either, and tend to attack people
    who offer opinions or try to make sense of some of your ideas.

    I should have known from past experience that that never ends well.
    'There's always something'.


    im not posting as personal blog and i answe a lot... the problem is you
    should first make soem work and understand what im talkin about and then answer it not just "i dont understand it so i will make z 10 hours of
    foam here"

    imagine what would come if anybody would start doing that agains ant
    book move piece of science in book etc...

    the amounts of foam would cover the sun :/ that would be word of foam
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From fir@[email protected] to comp.lang.c on Tue Oct 27 13:30:05 2026
    From Newsgroup: comp.lang.c

    fir pisze:
    bartc pisze:
    On 27/10/2026 11:57, fir wrote:
    bartc pisze:
    On 27/10/2026 08:37, fir wrote:

    blame the scienco fo doing just like tat

    (one solution is a solution untill you find better one) ..im just
    doing science here so its science to blame, i got no problem with that >>>>
    I've no idea what you mean. And I've no idea what it is you're
    actually after. I doubt anyone has. I doubt /you/ do!

    You suggest some new statement type, in a C language forum, somebody
    shows how to implement it in standard C, but your response is:

       "blame the scienco fo doing just like tat"

    Not:

      "Wow, thanks! That's perfect."

    My guess is that you're not interested in actual solutions. You're
    just thinking up one random idea after another. You don't care for
    anyone else's opinion or input.


    coz what yu say is like that and this is making bad content here


    science does that science is finding a solution then it finds another
    solution so you may blame science and say you got idea what science
    is actually after


    im just doin science - come to some conclusions than after that come
    to another conclusion...

    why your should problems with science should interest me? im here for
    doin science not to analyse personal problems of clc usersYour
    'science' seems to be writing mostly meaningless drivel and then
    posting reams of it in comp.lang.c as though it was your personal blog.

    You don't seem to expect any feedback either, and tend to attack
    people who offer opinions or try to make sense of some of your ideas.

    I should have known from past experience that that never ends well.
    'There's always something'.


    im not posting as personal blog and i answe a lot... the problem is you should first make soem work and understand what im talkin about and then answer it not just "i dont understand it so i will make z 10 hours of
    foam here"

    imagine what would come if anybody would start doing that agains ant
    book move piece of science in book etc...

    the amounts of foam would cover the sun :/ that would be word of foam


    also note i got a break (i dont know maybe like whole week a week a go
    and not posted here the group het ess active far ore bored becouse not
    much interesting topics appear

    so its better for me post some things and keep it more active/alive

    especially i got weary will make some few months of break again probbaly
    and it may be even dangerous for this group livehood maybe

    (esp now its no easy to get to usenet i think) so the attemots f keeping
    it more alive should be imo treated as good not bad


    but sparkling new topics and making foam is not the same.. as i sait i
    will try to code and post here up till end of year - what comes later i
    dont know (im not fully sure if i realize those plans being here yet
    whole 2 months as i may get weary also)
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From fir@[email protected] to comp.lang.c on Tue Oct 27 13:48:23 2026
    From Newsgroup: comp.lang.c

    bartc pisze:
    On 27/10/2026 11:57, fir wrote:
    bartc pisze:
    On 27/10/2026 08:37, fir wrote:

    blame the scienco fo doing just like tat

    (one solution is a solution untill you find better one) ..im just
    doing science here so its science to blame, i got no problem with that

    I've no idea what you mean. And I've no idea what it is you're
    actually after. I doubt anyone has. I doubt /you/ do!

    You suggest some new statement type, in a C language forum, somebody
    shows how to implement it in standard C, but your response is:

       "blame the scienco fo doing just like tat"

    Not:

      "Wow, thanks! That's perfect."

    My guess is that you're not interested in actual solutions. You're
    just thinking up one random idea after another. You don't care for
    anyone else's opinion or input.


    coz what yu say is like that and this is making bad content here


    science does that science is finding a solution then it finds another
    solution so you may blame science and say you got idea what science is
    actually after


    im just doin science - come to some conclusions than after that come
    to another conclusion...

    why your should problems with science should interest me? im here for
    doin science not to analyse personal problems of clc usersYour
    'science' seems to be writing mostly meaningless drivel and then
    posting reams of it in comp.lang.c as though it was your personal blog.

    You don't seem to expect any feedback either, and tend to attack people
    who offer opinions or try to make sense of some of your ideas.

    I should have known from past experience that that never ends well.
    'There's always something'.

    note btw on accusation you make foam you just make more foam (!)

    are you living in Foam Land ?
    --- Synchronet 3.22a-Linux NewsLink 1.2