• Re: Default signedness of 'plain' char.

    From Johann 'Myrkraverk' Oskarsson@johann@myrkraverk.invalid to comp.lang.c on Mon Aug 3 02:45:01 2026
    From Newsgroup: comp.lang.c

    On 02/08/2026 10:17 PM, Kenny McCormack wrote:
    First off, I know the "standards" answer is "Either is correct; you have no right to complain about anything", but I am not interested in the
    "standards" answer. If this is all you can do, then just click Next and go on.

    I'm interested in the "why" of why implementations might prefer one or the other.

    Consider:

    /* macro 'U' must be defined on the cmd line */
    #include <stdio.h>

    int main(void)
    {
    U char c = 255;

    printf("Result of 'c > 0': %d\n",c > 0);
    }

    And the following command lines:

    $ tcc -DU= -run CheckSignedChar.c
    $ tcc -DU=signed -run CheckSignedChar.c
    $ tcc -DU=unsigned -run CheckSignedChar.c

    On 32 bit RpiOS, the default is unsigned, but on x64 Ubuntu, the default is signed. I'm interested in what sorts of factors drive the decision-making.

    I believe some of it is to do with compatibility. The previous
    compiler, acc defined it signed, so when the next compiler on the same
    system, bcc, comes along they do it that way, even though bcc has been
    unsigned on the original system it was developed on.

    And why did acc define it signed in the first place? Maybe the CPU only
    had signed bytes, or they were faster than unsigned? I wouldn't know as
    this is a made up example.


    Note, BTW, that I first noticed this in a project using gcc, but it is
    easier to test using tcc, as above.

    Also, total aside, I'm surprised that one needs to do -DU= instead of just -DU. I thought -DU would define it as an empty string, but that generates
    a compile error. You need -DU=. Why?


    Yes, I had that problem before. Seems the tradition is to treat -Dfoo
    as

    #define foo 1

    rather than just

    #define foo

    so you need the added = to make it empty. It would be much better if
    this was taught in elementary C courses. But as it turns out, compiler
    arcana isn't taught much at all.
    --
    Johann | email: invalid -> com | http://www.myrkraverk.com/blog/
    I'm not from the Internet, I just work there. | via Easynews.com
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From gazelle@gazelle@shell.xmission.com (Kenny McCormack) to comp.lang.c on Mon Aug 3 01:47:09 2026
    From Newsgroup: comp.lang.c

    In article <PeMbS.103022$aXr.22087@fx18.ams4>,
    Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> wrote:
    ...
    And why did acc define it signed in the first place? Maybe the CPU only
    had signed bytes, or they were faster than unsigned? I wouldn't know as
    this is a made up example.

    Thank you for your response. I hope to see more responses on this thread.

    But, just out of curiosity, why do you way that "this is a made up example" ? To what are you referring and why do you think it was "made up" ?
    --
    A pervert, a racist, and a con man walk into a bar...

    Bartender says, "What will you have, Donald!"

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@david.brown@hesbynett.no to comp.lang.c on Mon Aug 3 09:56:49 2026
    From Newsgroup: comp.lang.c

    On 02/08/2026 16:17, Kenny McCormack wrote:
    First off, I know the "standards" answer is "Either is correct; you have no right to complain about anything", but I am not interested in the
    "standards" answer. If this is all you can do, then just click Next and go on.

    I'm interested in the "why" of why implementations might prefer one or the other.


    I agree it is an interesting question, but I don't think I have heard
    anything much other than "for compatibility reasons".

    I expect that from the earliest pre-standardisation days, some compilers treated "char" as signed and some as unsigned. So the standards
    solution was to let programmers be specified when they need to be (thus "signed char" and "unsigned char"), and let compiler writers keep "char"
    as they had done from before.

    Since characters at that time were pretty much only 7-bit, it did not
    really matter what signedness was used for character data. Perhaps the
    choice made a difference for implementation efficiency when extending to "int", or for comparisons. (I have worked with a processor - albeit a
    small microcontroller, rather than a typical target for C compilers -
    which could only do unsigned relational comparisons. "x < y" for signed
    types was therefore extra work, and "char" is naturally "unsigned char"
    on such targets.)

    Of course, in your own programming, if signedness matters then you
    should give it explicitly (or use more appropriate <stdint.h> types if
    you are handling small numbers rather than characters). That won't
    affect assumptions other people might have made in their code which can
    cause trouble for re-use. (gcc has "-fsigned-char" and
    "-funsigned-char" that can be of help when dealing with code that
    assumes a certain signedness of char.)

    Consider:

    /* macro 'U' must be defined on the cmd line */
    #include <stdio.h>

    int main(void)
    {
    U char c = 255;

    printf("Result of 'c > 0': %d\n",c > 0);
    }

    And the following command lines:

    $ tcc -DU= -run CheckSignedChar.c
    $ tcc -DU=signed -run CheckSignedChar.c
    $ tcc -DU=unsigned -run CheckSignedChar.c

    On 32 bit RpiOS, the default is unsigned, but on x64 Ubuntu, the default is signed. I'm interested in what sorts of factors drive the decision-making.

    Note, BTW, that I first noticed this in a project using gcc, but it is
    easier to test using tcc, as above.

    gcc has the same "-D" option, but you'd need two commands to build and
    run the program.


    Also, total aside, I'm surprised that one needs to do -DU= instead of just -DU. I thought -DU would define it as an empty string, but that generates
    a compile error. You need -DU=. Why?


    "-DU" gives the effect of "#define U 1". The most common use of
    command-line defines is with conditional compilation, so that you could
    have :

    #if U
    ...
    #endif

    Personally, I prefer to use "#ifdef U" or "#if defined(U)" constructs
    for such tests, and have my compiler complain about attempts to use
    undefined macros in any other way - that reduces the risk of undetected mistakes from typos in code using macros.




    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From antispam@antispam@fricas.org (Waldek Hebisch) to comp.lang.c on Mon Aug 3 13:48:59 2026
    From Newsgroup: comp.lang.c

    Kenny McCormack <gazelle@shell.xmission.com> wrote:
    First off, I know the "standards" answer is "Either is correct; you have no right to complain about anything", but I am not interested in the
    "standards" answer. If this is all you can do, then just click Next and go on.

    I'm interested in the "why" of why implementations might prefer one or the other.

    Consider:

    /* macro 'U' must be defined on the cmd line */
    #include <stdio.h>

    int main(void)
    {
    U char c = 255;

    printf("Result of 'c > 0': %d\n",c > 0);
    }

    And the following command lines:

    $ tcc -DU= -run CheckSignedChar.c
    $ tcc -DU=signed -run CheckSignedChar.c
    $ tcc -DU=unsigned -run CheckSignedChar.c

    On 32 bit RpiOS, the default is unsigned, but on x64 Ubuntu, the default is signed. I'm interested in what sorts of factors drive the decision-making.

    On original ARM one byte read was zero-extending. Sign extention
    needs 2 extra instructions. So, the question is: do you want
    1 instruction for reading characters or 3 instructions? If you
    choose 1 instruction you have choosen unsigned char.
    --
    Waldek Hebisch
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@cross@spitfire.i.gajendra.net (Dan Cross) to comp.lang.c on Mon Aug 3 14:47:23 2026
    From Newsgroup: comp.lang.c

    In article <114nji9$li5u$1@news.xmission.com>,
    Kenny McCormack <gazelle@shell.xmission.com> wrote:
    First off, I know the "standards" answer is "Either is correct; you have no >right to complain about anything", but I am not interested in the
    "standards" answer. If this is all you can do, then just click Next and go >on.

    I'm interested in the "why" of why implementations might prefer one or the >other.

    The original ANSI C rationale touches on this; to quote two
    excerpts:

    From section 1.1, when discussing "Keep the spirit of C", they
    mention, "Make it fast, even if it is not guaranteed to be
    portable" and about this, say the following:

    |The last proverb needs a little explanation. The potential for
    |eN4acient code generation is one of the most important strengths
    |of C. To help ensure that no code explosion occurs for what
    |appears to be a very simple operation, many operations are
    |deN4Uned to be _how the target machinerCOs hardware does it_ rather
    |than by a general abstract rule. An example of this willingness
    |to live with _what the machine does_ can be seen in the rules
    |that govern the widening of `char` objects for use in
    |expressions: whether the values of `char` objects widen to
    |signed or unsigned quantities typically depends on which byte
    |operation is more eN4acient on the target machine.

    That is, whether `char` is treated as signed or unsigned depends
    on the target. The precedent for this seems to be taken from
    history; later on, in the section on "Types" they write:

    |Three types of char are speciN4Ued: signed, plain, and unsigned.
    |A plain char may be represented as either signed or unsigned,
    |depending upon the implementation, as in prior practice.

    So the motivation for chosing one way or the other seems to be,
    "do what's fast" and the behavior originated in pre-standards C
    compilers.

    K&R1 chalks it up to machine differences, and says the following
    when discussion type conversions:

    |There is one subtle point about the conversion of characters to
    |integers. The language does not specify whether variables of
    |type `char` are signed or unsigned quantities. When a `char` is
    |converted to an `int`, can it ever produce a _negative_
    |integer? Unfortunately, this varies from machine to machine,
    |reflecting differences in architecture. On some machines
    |(PDP-ll, for instance), a `char` whose leftmost bit is 1 will
    i|be converted to a negative integer ("sign extension"). On
    |others, a `char` is promoted to an `int` by adding zeros at the
    |left end, and thus is always positive.
    |
    |The definition of C guarantees that any character in the
    |machine's standard character set will never be negative, so
    |these characters may be used freely in expressions as positive
    |quantities. But arbitrary bit patterns stored in to character
    |variables may appear be negative on some machines, yet positive
    |on others.
    |
    |The most common occurrence of this situation is when the value
    |-1 is used for EOF. Consider the code
    |
    | char c;
    |
    | c = getchar();
    | if (c == EOF)
    | ...
    |
    |On a machine which does not do sign extension, `c` is always
    |positive because it is a `char`, yet EOF is negative. As a
    |result, the test always fails. To avoid this, we have been
    |careful to use `int` instead of `char` for any variable which
    |holds a value returned by `getchar`.

    So the original motivation is differences between architectures
    with respect to sign extension when converting a char-sized
    quantity to something larger.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lew Pitcher@lew.pitcher@digitalfreehold.ca to comp.lang.c on Mon Aug 3 14:47:21 2026
    From Newsgroup: comp.lang.c

    On Sun, 02 Aug 2026 14:17:45 +0000, Kenny McCormack wrote:

    First off, I know the "standards" answer is "Either is correct; you have no right to complain about anything", but I am not interested in the
    "standards" answer. If this is all you can do, then just click Next and go on.

    I'm interested in the "why" of why implementations might prefer one or the other.

    Consider the effects of the integer promotion rules on a system with an 8-bit execution characterset (CHAR_BIT == 8) that has significant characters in the 0x80 through 0xff range[1], and how it affects the return results of functions like getchar(), getc(), and fgetc().

    A <<char>> is defined by the standard as being "large enough to store any member of the basic execution character set", and, when storing such an
    element "its value is guaranteed to be positive."

    So, with our hypothetical execution characterset (above), the compiler would have to consider <<char>> as unsigned. If it did not, then the getchar(), getc(), and fgetc() functions would return negative values for some characters, conflicting with the definition of EOF given in the standard.

    But, we rarely find our hypothetical execution characterset "out in the wild", so compilers (knowing the target execution characterset) often target <<char>> as a signed value.



    [snip]


    [1] Not as hypothetical as you might think; Some of the earliest C compilers (and current compilers as well) targetted the IBM EBCDIC systems, where much
    of the basic execution characterset resides between 0x80 and 0xff, with the numeric characters residing between 0xf0 and 0xf9. A signed <<char>> would
    not work here.
    --
    Lew Pitcher
    "In Skills We Trust"
    Not LLM output - I'm just like this.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lew Pitcher@lew.pitcher@digitalfreehold.ca to comp.lang.c on Mon Aug 3 15:04:38 2026
    From Newsgroup: comp.lang.c

    On Mon, 03 Aug 2026 14:47:21 +0000, Lew Pitcher wrote:

    On Sun, 02 Aug 2026 14:17:45 +0000, Kenny McCormack wrote:

    First off, I know the "standards" answer is "Either is correct; you have no >> right to complain about anything", but I am not interested in the
    "standards" answer. If this is all you can do, then just click Next and go >> on.

    I'm interested in the "why" of why implementations might prefer one or the >> other.

    Consider the effects of the integer promotion rules on a system with an 8-bit execution characterset (CHAR_BIT == 8) that has significant characters in the 0x80 through 0xff range[1], and how it affects the return results of functions
    like getchar(), getc(), and fgetc().
    [snip]
    [1] Not as hypothetical as you might think; Some of the earliest C compilers (and current compilers as well) targetted the IBM EBCDIC systems, where much of the basic execution characterset resides between 0x80 and 0xff, with the numeric characters residing between 0xf0 and 0xf9. A signed <<char>> would not work here.

    For what it's worth, this was also the reason (prior to Unicode) that C
    did not specify that alphabetic characters would have a contiguous sequence
    in the execution characterset. In EBCDIC, the alphabetics group a-i, j-r, s-z and A-I, J-R, S-Z, with various other characters (both assigned and unassigned) between the groupings.
    --
    Lew Pitcher
    "In Skills We Trust"
    Not LLM output - I'm just like this.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Johann 'Myrkraverk' Oskarsson@johann@myrkraverk.invalid to comp.lang.c,comp.sys.acorn.misc on Mon Aug 3 23:14:53 2026
    From Newsgroup: comp.lang.c

    On 03/08/2026 9:47 AM, Kenny McCormack wrote:
    In article <PeMbS.103022$aXr.22087@fx18.ams4>,
    Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> wrote:
    ...
    And why did acc define it signed in the first place? Maybe the CPU only
    had signed bytes, or they were faster than unsigned? I wouldn't know as
    this is a made up example.

    Thank you for your response. I hope to see more responses on this thread.

    But, just out of curiosity, why do you way that "this is a made up example" ? To what are you referring and why do you think it was "made up" ?


    Because I did not bother to dig up my RISC OS computer, and see what
    that C compiler did about the signedness of chars.

    It's a high chance that GCC, when ported to ARM for the first time,
    was compatible with whatever C compiler the original /Acorn/ team
    used, or made.

    I believe I have a continuation of that C compiler on my RISC OS
    machine. So assuming it still works, I can boot it up, and check
    what it does.

    That said, I'm in no hurry, and I'm not sure it still works. It's
    a /Pinebook/ that boots into RISC OS 5.

    Then, we should keep in mind that the /Acorn/ team was used to code
    in assembly. I believe most of RISC OS is coded in assembly, and
    their original C compiler was -- and had to be -- compatible with
    whatever /application binary interface/ they were used to in that
    assembly code.

    So, that's the reason I believe default ARM char is unsigned. I'm
    sure other regulars will be extremely happy to correct me, so let
    them. They enjoy that sport.

    I'm also adding comp.sys.acorn.misc, so the regulars there have a
    chance at correcting this historical tidbit. We'll leave alt.folk- lore.computers alone for now.
    --
    Johann | email: invalid -> com | http://www.myrkraverk.com/blog/
    I'm not from the Internet, I just work there. | via Easynews.com
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@bc@freeuk.com to comp.lang.c on Mon Aug 3 17:04:31 2026
    From Newsgroup: comp.lang.c

    On 03/08/2026 16:14, Johann 'Myrkraverk' Oskarsson wrote:
    On 03/08/2026 9:47 AM, Kenny McCormack wrote:
    In article <PeMbS.103022$aXr.22087@fx18.ams4>,
    Johann 'Myrkraverk' Oskarsson-a <johann@myrkraverk.invalid> wrote:
    ...
    And why did acc define it signed in the first place?-a Maybe the CPU only >>> had signed bytes, or they were faster than unsigned?-a I wouldn't know as >>> this is a made up example.

    Thank you for your response.-a-a I hope to see more responses on this
    thread.

    But, just out of curiosity, why do you way that "this is a made up
    example" ?
    To what are you referring and why do you think it was "made up" ?


    Because I did not bother to dig up my RISC OS computer, and see what
    that C compiler did about the signedness of chars.

    It's a high chance that GCC, when ported to ARM for the first time,
    was compatible with whatever C compiler the original /Acorn/ team
    used, or made.

    When I implemented C on Windows, I made 'char' unsigned (actually it was
    an alias for 'unsigned char'), as I thought a signed char was wrong.

    However, I ran into problems with programs that assumed a signed char.
    So I made it an alias for 'signed char' instead.

    Sometimes you just have to follow either the platform or existing
    practice, but it means crass choices like this persist.

    A more interesting fact for me is that signed 'char' is incompatible
    with 'signed char', and unsigned 'char' is incompatible with 'unsigned
    char', which introduces problems of its own. (Eg. what type does 'puts'
    take if called via an FFI where the C 'char' type does not exist.)


    I believe I have a continuation of that C compiler on my RISC OS
    machine.-a So assuming it still works, I can boot it up, and check
    what it does.

    That said, I'm in no hurry, and I'm not sure it still works.-a It's
    a /Pinebook/ that boots into RISC OS 5.

    According to Godbolt, C for ARM64 uses an unsigned 'char'. I hope
    because they realised that a signed 'char' makes no sense by itself.

    So, that's the reason I believe default ARM char is unsigned.-a I'm
    sure other regulars will be extremely happy to correct me, so let
    them.-a They enjoy that sport.

    I'm also adding comp.sys.acorn.misc,so the regulars there have a
    chance at correcting this historical tidbit.

    Please don't; why are you so obsessed with cross-posting everything in half-a-dozen unrelated groups?

    Why do you think they would be experts in the history of the C language
    or C compilers anyway? None of the threads there over the last two years
    give any evidence of that.

    Also, just because some application, library, system or language happens
    to be implemented in language X, (or some computer that happens to run
    some programs written in X!) doesn't mean it it topical in a newsgroup
    devoted to that language.

    Most newsgroups are pretty much dead anyway and are either wastelands or cesspits; I hope you're not trying to turn this into the latter.

    If you want a more appreciative (and younger) audience, try Reddit.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Johann 'Myrkraverk' Oskarsson@johann@myrkraverk.invalid to comp.lang.c on Tue Aug 4 00:23:11 2026
    From Newsgroup: comp.lang.c

    On 04/08/2026 12:04 AM, bart wrote:
    On 03/08/2026 16:14, Johann 'Myrkraverk' Oskarsson wrote:
    On 03/08/2026 9:47 AM, Kenny McCormack wrote:
    In article <PeMbS.103022$aXr.22087@fx18.ams4>,
    Johann 'Myrkraverk' Oskarsson-a <johann@myrkraverk.invalid> wrote:
    ...
    And why did acc define it signed in the first place?-a Maybe the CPU
    only
    had signed bytes, or they were faster than unsigned?-a I wouldn't
    know as
    this is a made up example.

    Thank you for your response.-a-a I hope to see more responses on this
    thread.

    But, just out of curiosity, why do you way that "this is a made up
    example" ?
    To what are you referring and why do you think it was "made up" ?


    Because I did not bother to dig up my RISC OS computer, and see what
    that C compiler did about the signedness of chars.

    It's a high chance that GCC, when ported to ARM for the first time,
    was compatible with whatever C compiler the original /Acorn/ team
    used, or made.

    When I implemented C on Windows, I made 'char' unsigned (actually it was
    an alias for 'unsigned char'), as I thought a signed char was wrong.

    However, I ran into problems with programs that assumed a signed char.
    So I made it an alias for 'signed char' instead.

    Sometimes you just have to follow either the platform or existing
    practice, but it means crass choices like this persist.

    A more interesting fact for me is that signed 'char' is incompatible
    with 'signed char', and unsigned 'char' is incompatible with 'unsigned char', which introduces problems of its own. (Eg. what type does 'puts'
    take if called via an FFI where the C 'char' type does not exist.)


    I believe I have a continuation of that C compiler on my RISC OS
    machine.-a So assuming it still works, I can boot it up, and check
    what it does.

    That said, I'm in no hurry, and I'm not sure it still works.-a It's
    a /Pinebook/ that boots into RISC OS 5.

    According to Godbolt, C for ARM64 uses an unsigned 'char'. I hope
    because they realised that a signed 'char' makes no sense by itself.

    So, that's the reason I believe default ARM char is unsigned.-a I'm
    sure other regulars will be extremely happy to correct me, so let
    them.-a They enjoy that sport.

    I'm also adding comp.sys.acorn.misc,so the regulars there have a
    chance at correcting this historical tidbit.

    Please don't; why are you so obsessed with cross-posting everything in half-a-dozen unrelated groups?

    Why do you think they would be experts in the history of the C language
    or C compilers anyway? None of the threads there over the last two years give any evidence of that.

    You really need to ask me that question, and remove the cross posting?
    Why not ask them, like a regular human being?

    Also, just because some application, library, system or language happens
    to be implemented in language X, (or some computer that happens to run
    some programs written in X!) doesn't mean it it topical in a newsgroup devoted to that language.

    Most newsgroups are pretty much dead anyway and are either wastelands or cesspits; I hope you're not trying to turn this into the latter.

    If you want a more appreciative (and younger) audience, try Reddit.



    Dear bart, as you seem to be trying not to be an asshole, I'll deign to
    reply and try not to be an asshole too.

    I've been with the "younger" crowd, on Discord. They're even more
    problematic than comp.lang.c. I escaped with the little hair I have
    left, see picture on my BlueSky.

    What you all fail no notice, is that you're all so covered with feces
    and spread it around wherever you go, that you're the ones making this
    last bastion of Usenet a cesspit.

    Once you, Dan Cross, Keith Thompson, Scott Lurndal, and Lawrence
    D'Oliveiro realize you're the ones causing the trouble, we may, just
    may, have a decent conversation.

    I do not conform to your "group think" about how C is supposed to work,
    and that bothers all of you. You may not realize it, and I'm stepping
    into parapsychology here, but that's why you don't like me. Once you're willing to accept that people have different opinions, or should I say, /belief/, about how a C compiler should behave, you'll realize you're
    the ones pushing everyone else out of comp.lang.c.

    Nobody likes a true believer who spreads his and her religioun all over
    their social contacts. Stop it, or face the consequences of the Spanish Inquisition!
    --
    Johann | email: invalid -> com | http://www.myrkraverk.com/blog/
    I'm not from the Internet, I just work there. | via Easynews.com https://bsky.app/profile/myrkraverk.bsky.social
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@bc@freeuk.com to comp.lang.c on Mon Aug 3 18:03:51 2026
    From Newsgroup: comp.lang.c

    On 03/08/2026 17:23, Johann 'Myrkraverk' Oskarsson wrote:
    On 04/08/2026 12:04 AM, bart wrote:

    Why do you think they would be experts in the history of the C
    language or C compilers anyway? None of the threads there over the
    last two years give any evidence of that.

    You really need to ask me that question, and remove the cross posting?
    Why not ask them, like a regular human being?

    I'm asking you because you're the one constantly adding new groups.
    You've admitted you like doing it to annoy people.

    So /you're/ being the asshole.



    Also, just because some application, library, system or language
    happens to be implemented in language X, (or some computer that
    happens to run some programs written in X!) doesn't mean it it topical
    in a newsgroup devoted to that language.

    Most newsgroups are pretty much dead anyway and are either wastelands
    or cesspits; I hope you're not trying to turn this into the latter.

    If you want a more appreciative (and younger) audience, try Reddit.



    Dear bart, as you seem to be trying not to be an asshole, I'll deign to
    reply and try not to be an asshole too.

    I've been with the "younger" crowd, on Discord.-a They're even more problematic than comp.lang.c.-a I escaped with the little hair I have
    left, see picture on my BlueSky.

    What you all fail no notice, is that you're all so covered with feces
    and spread it around wherever you go, that you're the ones making this
    last bastion of Usenet a cesspit.

    Once you, Dan Cross, Keith Thompson, Scott Lurndal, and Lawrence
    D'Oliveiro realize you're the ones causing the trouble, we may, just
    may, have a decent conversation.

    That's going to be unlikely with you, sorry.

    (Also, /I'm/ the one who has long been considered the upstart here by
    asking too many questions and going against the grain.

    However, I've usually respected topicality.)

    Nobody likes a true believer who spreads his and her religioun all over
    their social contacts.-a Stop it, or face the consequences of the Spanish Inquisition!

    So what religion are you spreading? Does it have anything to do with
    .... C? I don't mean you've used a program written in a language
    compiled with a program that might have been written in C.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Johann 'Myrkraverk' Oskarsson@johann@myrkraverk.invalid to comp.lang.c on Tue Aug 4 01:26:44 2026
    From Newsgroup: comp.lang.c

    On 04/08/2026 1:03 AM, bart wrote:
    On 03/08/2026 17:23, Johann 'Myrkraverk' Oskarsson wrote:
    On 04/08/2026 12:04 AM, bart wrote:

    Why do you think they would be experts in the history of the C
    language or C compilers anyway? None of the threads there over the
    last two years give any evidence of that.

    You really need to ask me that question, and remove the cross posting?
    Why not ask them, like a regular human being?

    I'm asking you because you're the one constantly adding new groups.
    You've admitted you like doing it to annoy people.

    So /you're/ being the asshole.


    Disrespect breeds disrespect. That you fail to understand this tells
    me you're a psychopath, or an LLM.



    Also, just because some application, library, system or language
    happens to be implemented in language X, (or some computer that
    happens to run some programs written in X!) doesn't mean it it
    topical in a newsgroup devoted to that language.

    Most newsgroups are pretty much dead anyway and are either wastelands
    or cesspits; I hope you're not trying to turn this into the latter.

    If you want a more appreciative (and younger) audience, try Reddit.



    Dear bart, as you seem to be trying not to be an asshole, I'll deign to
    reply and try not to be an asshole too.

    I've been with the "younger" crowd, on Discord.-a They're even more
    problematic than comp.lang.c.-a I escaped with the little hair I have
    left, see picture on my BlueSky.

    What you all fail no notice, is that you're all so covered with feces
    and spread it around wherever you go, that you're the ones making this
    last bastion of Usenet a cesspit.

    Once you, Dan Cross, Keith Thompson, Scott Lurndal, and Lawrence
    D'Oliveiro realize you're the ones causing the trouble, we may, just
    may, have a decent conversation.

    That's going to be unlikely with you, sorry.

    Don't lie. You're not sorry at all. And also, since you failed to
    notice it, all of you are behaving like psychopaths. I don't respect psychopaths.


    (Also, /I'm/ the one who has long been considered the upstart here by
    asking too many questions and going against the grain.

    However, I've usually respected topicality.)

    No, you don't.


    Nobody likes a true believer who spreads his and her religioun all over
    their social contacts.-a Stop it, or face the consequences of the Spanish
    Inquisition!

    So what religion are you spreading? Does it have anything to do
    with .... C? I don't mean you've used a program written in a language compiled with a program that might have been written in C.

    I'm pointing out that you, the "regulars" in comp.lang.c are spreading
    your religion. That you fail no notice tells me that you don't consider yourself a /believer/. Hence, there's no point in talking to you.

    Just talk to the hand.
    --
    Johann | email: invalid -> com | http://www.myrkraverk.com/blog/
    I'm not from the Internet, I just work there. | via Easynews.com https://bsky.app/profile/myrkraverk.bsky.social
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From BGB@cr88192@gmail.com to comp.lang.c on Mon Aug 3 13:56:57 2026
    From Newsgroup: comp.lang.c

    On 8/3/2026 2:56 AM, David Brown wrote:
    On 02/08/2026 16:17, Kenny McCormack wrote:
    First off, I know the "standards" answer is "Either is correct; you
    have no
    right to complain about anything", but I am not interested in the
    "standards" answer.-a If this is all you can do, then just click Next
    and go
    on.

    I'm interested in the "why" of why implementations might prefer one or
    the
    other.


    I agree it is an interesting question, but I don't think I have heard anything much other than "for compatibility reasons".

    I expect that from the earliest pre-standardisation days, some compilers treated "char" as signed and some as unsigned.-a So the standards
    solution was to let programmers be specified when they need to be (thus "signed char" and "unsigned char"), and let compiler writers keep "char"
    as they had done from before.

    Since characters at that time were pretty much only 7-bit, it did not
    really matter what signedness was used for character data.-a Perhaps the choice made a difference for implementation efficiency when extending to "int", or for comparisons.-a (I have worked with a processor - albeit a small microcontroller, rather than a typical target for C compilers -
    which could only do unsigned relational comparisons.-a "x < y" for signed types was therefore extra work, and "char" is naturally "unsigned char"
    on such targets.)

    Of course, in your own programming, if signedness matters then you
    should give it explicitly (or use more appropriate <stdint.h> types if
    you are handling small numbers rather than characters).-a That won't
    affect assumptions other people might have made in their code which can cause trouble for re-use.-a (gcc has "-fsigned-char" and "-funsigned-
    char" that can be of help when dealing with code that assumes a certain signedness of char.)


    In my case, I went with signed for my targets, as that is what most code expects.

    Had noted when porting code to ARM based targets that this is a frequent
    pain point, as there is a lot of code around that tends to assume that
    plain char is signed. Not usually a hard fix, but an annoying one.


    I remembered also once (long ago) that I tried implementing a (now
    misplaced) version of BGBCC that tried to target ARM (mostly
    ARM11/Thumb2 at the time), but performance was so dismal that I just
    stuck with GCC and (occasionally) transpiling stuff to C and feeding it through GCC (still gave faster results).

    Though, was generating some pretty awful code; and the ARM11 chips
    didn't exactly hide the poor performance of inefficient code (and the
    ISA wasn't super friendly in some ways; but I made the possibly mistaken
    idea to target Thumb2 as the primary codegen strategy).


    Consider:

    /* macro 'U' must be defined on the cmd line */
    #include <stdio.h>

    int main(void)
    {
    -a-a-a-a U char c = 255;

    -a-a-a-a printf("Result of 'c > 0': %d\n",c > 0);
    }

    And the following command lines:

    $ tcc -DU= -run CheckSignedChar.c
    $ tcc -DU=signed -run CheckSignedChar.c
    $ tcc -DU=unsigned -run CheckSignedChar.c

    On 32 bit RpiOS, the default is unsigned, but on x64 Ubuntu, the
    default is
    signed.-a I'm interested in what sorts of factors drive the decision-
    making.

    Note, BTW, that I first noticed this in a project using gcc, but it is
    easier to test using tcc, as above.

    gcc has the same "-D" option, but you'd need two commands to build and
    run the program.


    Also, total aside, I'm surprised that one needs to do -DU= instead of
    just
    -DU.-a I thought -DU would define it as an empty string, but that
    generates
    a compile error.-a You need -DU=.-a Why?


    "-DU" gives the effect of "#define U 1".-a The most common use of command-line defines is with conditional compilation, so that you could
    have :

    #if U
    ...
    #endif

    Personally, I prefer to use "#ifdef U" or "#if defined(U)" constructs
    for such tests, and have my compiler complain about attempts to use undefined macros in any other way - that reduces the risk of undetected mistakes from typos in code using macros.





    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c on Mon Aug 3 13:20:07 2026
    From Newsgroup: comp.lang.c

    On 8/2/2026 7:17 AM, Kenny McCormack wrote:
    First off, I know the "standards" answer is "Either is correct; you have no right to complain about anything", but I am not interested in the
    "standards" answer. If this is all you can do, then just click Next and go on.

    I'm interested in the "why" of why implementations might prefer one or the other.

    Consider:

    /* macro 'U' must be defined on the cmd line */
    #include <stdio.h>

    int main(void)
    {
    U char c = 255;

    printf("Result of 'c > 0': %d\n",c > 0);
    }

    And the following command lines:

    $ tcc -DU= -run CheckSignedChar.c
    $ tcc -DU=signed -run CheckSignedChar.c
    $ tcc -DU=unsigned -run CheckSignedChar.c

    On 32 bit RpiOS, the default is unsigned, but on x64 Ubuntu, the default is signed. I'm interested in what sorts of factors drive the decision-making.

    Note, BTW, that I first noticed this in a project using gcc, but it is
    easier to test using tcc, as above.

    Also, total aside, I'm surprised that one needs to do -DU= instead of just -DU. I thought -DU would define it as an empty string, but that generates
    a compile error. You need -DU=. Why?


    The sign of char is just what the underlying system needs to do its
    thing. If you want a signed char, just signed char. ;^)

    fwiw, I personally prefer unsigned char for all of my raw buffers and
    such, but that's just me.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@bc@freeuk.com to comp.lang.c on Mon Aug 3 22:06:38 2026
    From Newsgroup: comp.lang.c

    On 03/08/2026 21:20, Chris M. Thomasson wrote:
    On 8/2/2026 7:17 AM, Kenny McCormack wrote:
    First off, I know the "standards" answer is "Either is correct; you
    have no
    right to complain about anything", but I am not interested in the
    "standards" answer.-a If this is all you can do, then just click Next
    and go
    on.

    I'm interested in the "why" of why implementations might prefer one or
    the
    other.

    Consider:

    /* macro 'U' must be defined on the cmd line */
    #include <stdio.h>

    int main(void)
    {
    -a-a-a-a U char c = 255;

    -a-a-a-a printf("Result of 'c > 0': %d\n",c > 0);
    }

    And the following command lines:

    $ tcc -DU= -run CheckSignedChar.c
    $ tcc -DU=signed -run CheckSignedChar.c
    $ tcc -DU=unsigned -run CheckSignedChar.c

    On 32 bit RpiOS, the default is unsigned, but on x64 Ubuntu, the
    default is
    signed.-a I'm interested in what sorts of factors drive the decision-
    making.

    Note, BTW, that I first noticed this in a project using gcc, but it is
    easier to test using tcc, as above.

    Also, total aside, I'm surprised that one needs to do -DU= instead of
    just
    -DU.-a I thought -DU would define it as an empty string, but that
    generates
    a compile error.-a You need -DU=.-a Why?


    The sign of char is just what the underlying system needs to do its
    thing. If you want a signed char, just signed char. ;^)

    It's not that simple. Very many libraries including the standard library
    make use of char* for strings for example. And string literals will be
    char* too.

    So you have to play along, you can't just use signed char* or unsigned
    char*; compilers will complain.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c on Mon Aug 3 14:25:06 2026
    From Newsgroup: comp.lang.c

    On 8/3/2026 2:06 PM, bart wrote:
    On 03/08/2026 21:20, Chris M. Thomasson wrote:
    On 8/2/2026 7:17 AM, Kenny McCormack wrote:
    First off, I know the "standards" answer is "Either is correct; you
    have no
    right to complain about anything", but I am not interested in the
    "standards" answer.-a If this is all you can do, then just click Next
    and go
    on.

    I'm interested in the "why" of why implementations might prefer one
    or the
    other.

    Consider:

    /* macro 'U' must be defined on the cmd line */
    #include <stdio.h>

    int main(void)
    {
    -a-a-a-a U char c = 255;

    -a-a-a-a printf("Result of 'c > 0': %d\n",c > 0);
    }

    And the following command lines:

    $ tcc -DU= -run CheckSignedChar.c
    $ tcc -DU=signed -run CheckSignedChar.c
    $ tcc -DU=unsigned -run CheckSignedChar.c

    On 32 bit RpiOS, the default is unsigned, but on x64 Ubuntu, the
    default is
    signed.-a I'm interested in what sorts of factors drive the decision-
    making.

    Note, BTW, that I first noticed this in a project using gcc, but it is
    easier to test using tcc, as above.

    Also, total aside, I'm surprised that one needs to do -DU= instead of
    just
    -DU.-a I thought -DU would define it as an empty string, but that
    generates
    a compile error.-a You need -DU=.-a Why?


    The sign of char is just what the underlying system needs to do its
    thing. If you want a signed char, just signed char. ;^)

    It's not that simple. Very many libraries including the standard library make use of char* for strings for example. And string literals will be
    char* too.

    So you have to play along, you can't just use signed char* or unsigned char*; compilers will complain.



    I use unsigned char for my personal buffers. If a char is signed or not
    is up to the impl. C std besides the point here. If I want to use a C function, I know how to do it.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From BGB@cr88192@gmail.com to comp.lang.c on Mon Aug 3 18:38:03 2026
    From Newsgroup: comp.lang.c

    On 8/3/2026 4:25 PM, Chris M. Thomasson wrote:
    On 8/3/2026 2:06 PM, bart wrote:
    On 03/08/2026 21:20, Chris M. Thomasson wrote:
    On 8/2/2026 7:17 AM, Kenny McCormack wrote:
    First off, I know the "standards" answer is "Either is correct; you
    have no
    right to complain about anything", but I am not interested in the
    "standards" answer.-a If this is all you can do, then just click Next >>>> and go
    on.

    I'm interested in the "why" of why implementations might prefer one
    or the
    other.

    Consider:

    /* macro 'U' must be defined on the cmd line */
    #include <stdio.h>

    int main(void)
    {
    -a-a-a-a U char c = 255;

    -a-a-a-a printf("Result of 'c > 0': %d\n",c > 0);
    }

    And the following command lines:

    $ tcc -DU= -run CheckSignedChar.c
    $ tcc -DU=signed -run CheckSignedChar.c
    $ tcc -DU=unsigned -run CheckSignedChar.c

    On 32 bit RpiOS, the default is unsigned, but on x64 Ubuntu, the
    default is
    signed.-a I'm interested in what sorts of factors drive the decision- >>>> making.

    Note, BTW, that I first noticed this in a project using gcc, but it is >>>> easier to test using tcc, as above.

    Also, total aside, I'm surprised that one needs to do -DU= instead
    of just
    -DU.-a I thought -DU would define it as an empty string, but that
    generates
    a compile error.-a You need -DU=.-a Why?


    The sign of char is just what the underlying system needs to do its
    thing. If you want a signed char, just signed char. ;^)

    It's not that simple. Very many libraries including the standard
    library make use of char* for strings for example. And string literals
    will be char* too.

    So you have to play along, you can't just use signed char* or unsigned
    char*; compilers will complain.



    I use unsigned char for my personal buffers. If a char is signed or not
    is up to the impl. C std besides the point here. If I want to use a C function, I know how to do it.

    I typically do:
    typedef unsigned char byte; //often
    typedef signed char sbyte; //sometimes


    Then often u16/u32/u64, s16/s32/s64, ...

    But, mostly because even with C99, "uint64_t" and similar are enough
    typing to be more annoying (whenever one feels a need for an exact-width type). Had started gradually shifting to using the C99 types as a
    reference point, as I am no longer actively using compilers that don't
    support the C99 "stdint.h" stuff (though last I checked, MSVC still
    doesn't fully support C99; eg, still no VLAs or _Complex).

    ...


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@Keith.S.Thompson+u@gmail.com to comp.lang.c on Mon Aug 3 16:58:39 2026
    From Newsgroup: comp.lang.c

    Lew Pitcher <lew.pitcher@digitalfreehold.ca> writes:
    [...]
    For what it's worth, this was also the reason (prior to Unicode)
    that C did not specify that alphabetic characters would have a
    contiguous sequence in the execution characterset. In EBCDIC,
    the alphabetics group a-i, j-r, s-z and A-I, J-R, S-Z, with
    various other characters (both assigned and unassigned) between
    the groupings.

    C still doesn't require Unicode (well, mostly), and still doesn't
    require 'i'+1=='j'. C does have UTF-8 string literals, such as
    u8"hello", which are encoded as UTF-8, but ordinary string literals
    like "hello" are still encoded using the execution character set,
    which could be EBCDIC.

    There's a proposal to require 'a'..'f' and 'A'..'F' to be contiguous,
    but it hasn't appeared in the latest C2y draft.

    https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3192.pdf

    I suppose that an implementation whose execution character set is
    some version of EBCDIC would have to treat "hello" and u8"hello"
    very differently.
    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c on Mon Aug 3 19:34:12 2026
    From Newsgroup: comp.lang.c

    On 8/3/2026 4:38 PM, BGB wrote:
    On 8/3/2026 4:25 PM, Chris M. Thomasson wrote:
    On 8/3/2026 2:06 PM, bart wrote:
    On 03/08/2026 21:20, Chris M. Thomasson wrote:
    On 8/2/2026 7:17 AM, Kenny McCormack wrote:
    First off, I know the "standards" answer is "Either is correct; you >>>>> have no
    right to complain about anything", but I am not interested in the
    "standards" answer.-a If this is all you can do, then just click
    Next and go
    on.

    I'm interested in the "why" of why implementations might prefer one >>>>> or the
    other.

    Consider:

    /* macro 'U' must be defined on the cmd line */
    #include <stdio.h>

    int main(void)
    {
    -a-a-a-a U char c = 255;

    -a-a-a-a printf("Result of 'c > 0': %d\n",c > 0);
    }

    And the following command lines:

    $ tcc -DU= -run CheckSignedChar.c
    $ tcc -DU=signed -run CheckSignedChar.c
    $ tcc -DU=unsigned -run CheckSignedChar.c

    On 32 bit RpiOS, the default is unsigned, but on x64 Ubuntu, the
    default is
    signed.-a I'm interested in what sorts of factors drive the
    decision- making.

    Note, BTW, that I first noticed this in a project using gcc, but it is >>>>> easier to test using tcc, as above.

    Also, total aside, I'm surprised that one needs to do -DU= instead
    of just
    -DU.-a I thought -DU would define it as an empty string, but that
    generates
    a compile error.-a You need -DU=.-a Why?


    The sign of char is just what the underlying system needs to do its
    thing. If you want a signed char, just signed char. ;^)

    It's not that simple. Very many libraries including the standard
    library make use of char* for strings for example. And string
    literals will be char* too.

    So you have to play along, you can't just use signed char* or
    unsigned char*; compilers will complain.



    I use unsigned char for my personal buffers. If a char is signed or
    not is up to the impl. C std besides the point here. If I want to use
    a C function, I know how to do it.

    I typically do:
    -a typedef unsigned char byte;-a-a-a //often
    -a typedef signed char sbyte;-a-a-a //sometimes

    I also remember using the word, word a lot... ;^)

    Not for bytes, but for things like uintptr_t. Always found it useful.

    A double word struct is comprised of two adjacent words.


    struct anchor
    {
    word m_part_0;
    word m_part_1;
    };

    make sure with a static assert or something that the sizeof(struct
    anchor) == (sizeof(word) * 2)

    Fwiw, it works well with the CMPXCH8B or CMPXCHG16B instructions on x86. Double width atomic CAS.


    Then often u16/u32/u64, s16/s32/s64, ...

    But, mostly because even with C99, "uint64_t" and similar are enough
    typing to be more annoying (whenever one feels a need for an exact-width type). Had started gradually shifting to using the C99 types as a
    reference point, as I am no longer actively using compilers that don't support the C99 "stdint.h" stuff (though last I checked, MSVC still
    doesn't fully support C99; eg, still no VLAs or _Complex).
    Its been a while since I used c99 on windows, but iirc, their (MSVC)
    support for complex numbers was total crap. I think there was a way to
    get it working, but it was not std at all. Iirc the last GCC I used had
    good support for std complex numbers in C99.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Theo@theom+news@chiark.greenend.org.uk to comp.lang.c,comp.sys.acorn.misc on Tue Aug 4 13:13:22 2026
    From Newsgroup: comp.lang.c

    In comp.sys.acorn.misc Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> wrote:
    On 03/08/2026 9:47 AM, Kenny McCormack wrote:
    In article <PeMbS.103022$aXr.22087@fx18.ams4>,
    Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> wrote:
    ...
    And why did acc define it signed in the first place? Maybe the CPU only >> had signed bytes, or they were faster than unsigned? I wouldn't know as >> this is a made up example.

    Thank you for your response. I hope to see more responses on this thread.

    But, just out of curiosity, why do you way that "this is a made up example" ?
    To what are you referring and why do you think it was "made up" ?


    Because I did not bother to dig up my RISC OS computer, and see what
    that C compiler did about the signedness of chars.

    It's a high chance that GCC, when ported to ARM for the first time,
    was compatible with whatever C compiler the original /Acorn/ team
    used, or made.

    I believe I have a continuation of that C compiler on my RISC OS
    machine. So assuming it still works, I can boot it up, and check
    what it does.

    I don't have Norcroft C handy to check, but I expect chars are also
    unsigned.

    I wasn't there at the time, but I can make an informed guess as to why. I think it was Steve Furber who famously said that Acorn gave them two unique things when designing the original ARM1: no people and no money. That meant that everything had to be incredibly simple, because they didn't have transistors for anything else.

    That's why the 32 bit ISA has the instruction:
    LDR Rd,[Ra, #n]
    for a 32 bit load, and
    LDRB Rd,[Ra, #n]
    for an 8 bit load.

    Internally, the 8 bit load is just a 4-to-1 mux x 8 bits of the 32 bit
    version. There was no sign extension logic on that datapath (would have
    cost transistors and reduced clock speed), so the read value has zeros in
    the upper 24 bits.

    Also, in that vein, you can easily merge four 8 bit values in registers into a 32-bit word:
    ORR Rd,Rs0,Rs1,LSL#8
    ORR Rd, Rd,Rs2,LSL#16
    ORR Rd, Rd,Rs3,LSL#24

    which sign extension would mess up (you'd have to mask off the sign bits first).

    With that, it's natural for chars to be unsigned. It enables a lot of the
    bit- and byte-twiddling that the A32 instruction set is good at.

    Then, we should keep in mind that the /Acorn/ team was used to code
    in assembly. I believe most of RISC OS is coded in assembly, and
    their original C compiler was -- and had to be -- compatible with
    whatever /application binary interface/ they were used to in that
    assembly code.

    Assembly was popular because A32 assembly is nice to write. Acorn had C and Modula2 compilers from early on (~1985-6), but as an outside developer they cost a couple of hundred pounds (in 1980s money) while an assembler was included in BBC BASIC V in ROM. So there was a natural bias towards
    assembly and BASIC (which works much like raw assembly; no linker)
    programming for non-professional developers. In BBC BASIC bytes are
    unsigned.

    The OS interfaces (SWIs, like Unix syscalls but much broader and extensible) were defined for assembly-first, with shims for calling from C (primarily to force register allocation to match what the SWI wanted; SWIs typically use 8 registers for arguments while C only uses 4 plus the stack). This interface doesn't document explicit types as everything is just a 32 bit word
    (although they can be retrofitted, eg via OSLib) but in practice most values are either 32 bit signed/unsigned or 8 bit unsigned (eg in structs).

    At the time Acorn had two assemblers: AAsm, which only generated standalone assembly output, and ObjAsm which played nicely with the C Linker. So there was indeed a whole other world which was assembly-only and didn't need to
    worry about C. When you were using C, object files were in the Acorn Object Format (AOF) and used the Arm Procedure Calling Standard (APCS-R for RISC
    OS with 26-bit PC; APCS-A was an earlier version for Arthur).

    Nick Burrett did most of the early porting work on GCC for RISC OS circa
    1991; since the whole Acorn world was using AOF and APCS-R, in order to be cross-compatible with libraries that was what GCC had to generate. When upstream GCC moved on to ELF, for a long time we had to maintain AOF output
    to keep compatibility (RISC OS GCC 3.4.6 [I think] is the last AOF
    version; GCC 4 uses ELF).

    So, that's the reason I believe default ARM char is unsigned. I'm
    sure other regulars will be extremely happy to correct me, so let
    them. They enjoy that sport.

    So TL;DR, as I see it:

    - the architecture made its 8 bit datatype zero-extended because it
    was the cheapest thing to do in silicon
    - assembly programmers used unsigned 8-bit datatypes because that's what the architecture made easy and cheap, but also because it was the most natural
    - BBC BASIC on the 6502 had unsigned bytes and those carried over to ARM BBC BASIC
    - Acorn C followed their lead
    - GCC naturally had to follow what Acorn C did
    - in all cases it was the best fit for the architecture anyway

    Theo
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From scott@scott@slp53.sl.home (Scott Lurndal) to comp.lang.c on Tue Aug 4 15:50:55 2026
    From Newsgroup: comp.lang.c

    Lew Pitcher <lew.pitcher@digitalfreehold.ca> writes:
    On Mon, 03 Aug 2026 16:58:39 -0700, Keith Thompson wrote:

    Lew Pitcher <lew.pitcher@digitalfreehold.ca> writes:
    [...]
    For what it's worth, this was also the reason (prior to Unicode)
    that C did not specify that alphabetic characters would have a
    contiguous sequence in the execution characterset. In EBCDIC,
    the alphabetics group a-i, j-r, s-z and A-I, J-R, S-Z, with
    various other characters (both assigned and unassigned) between
    the groupings.

    C still doesn't require Unicode (well, mostly),

    Yes. I mentioned Unicode because it both simplifies /and/ complicates
    the matter of alphabetic value contiguity; While it ensures that contiguity >within an alphabet, it does not ensure contiguity between alphabets (not
    that I think it should), leading to the same problem that EBCDIC presented
    in the first place.

    and still doesn't require 'i'+1=='j'.

    I pointed that out because it has become a common programmer misconception; >hand rolled isalpha-like functions often express themselves with a range >check in the form of
    is_lower_case = ((some_char >= 'a') && (some_char <= 'z'));
    is_upper_case = ((some_char >= 'A') && (some_char <= 'Z'));

    The standard explicitly requires /numeric/ characters to have contiguity, >though.
    is_number = ((some_char >= '0') && (some_char <= '9'));


    C does have UTF-8 string literals, such as
    u8"hello", which are encoded as UTF-8, but ordinary string literals
    like "hello" are still encoded using the execution character set,
    which could be EBCDIC.

    There's a proposal to require 'a'..'f' and 'A'..'F' to be contiguous,
    but it hasn't appeared in the latest C2y draft.

    https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3192.pdf

    That's going to complicate the mainframe C compilers a bit :-)

    Not really. Even in EBCDIC, the encodings for both upper
    and lower-case A-F are contiguous, as required by n3192.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From antispam@antispam@fricas.org (Waldek Hebisch) to comp.lang.c on Tue Aug 4 18:10:37 2026
    From Newsgroup: comp.lang.c

    Lew Pitcher <lew.pitcher@digitalfreehold.ca> wrote:
    On Mon, 03 Aug 2026 14:47:21 +0000, Lew Pitcher wrote:

    On Sun, 02 Aug 2026 14:17:45 +0000, Kenny McCormack wrote:

    First off, I know the "standards" answer is "Either is correct; you have no >>> right to complain about anything", but I am not interested in the
    "standards" answer. If this is all you can do, then just click Next and go >>> on.

    I'm interested in the "why" of why implementations might prefer one or the >>> other.

    Consider the effects of the integer promotion rules on a system with an 8-bit
    execution characterset (CHAR_BIT == 8) that has significant characters in the
    0x80 through 0xff range[1], and how it affects the return results of functions
    like getchar(), getc(), and fgetc().
    [snip]
    [1] Not as hypothetical as you might think; Some of the earliest C compilers >> (and current compilers as well) targetted the IBM EBCDIC systems, where much >> of the basic execution characterset resides between 0x80 and 0xff, with the >> numeric characters residing between 0xf0 and 0xf9. A signed <<char>> would >> not work here.

    For what it's worth, this was also the reason (prior to Unicode) that C
    did not specify that alphabetic characters would have a contiguous sequence in the execution characterset. In EBCDIC, the alphabetics group a-i, j-r, s-z and A-I, J-R, S-Z, with various other characters (both assigned and unassigned)
    between the groupings.

    Unless you are payed specifically to do so I see no reason to support
    EBCDIC. Of course, IBM have enough influence to keep C standard
    as it is regarding character set, but it does not mean that anybody
    else should take is seriously.
    --
    Waldek Hebisch
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Johann 'Myrkraverk' Oskarsson@johann@myrkraverk.invalid to comp.lang.c on Wed Aug 5 03:17:35 2026
    From Newsgroup: comp.lang.c

    On 05/08/2026 2:10 AM, Waldek Hebisch wrote:
    Lew Pitcher <lew.pitcher@digitalfreehold.ca> wrote:
    On Mon, 03 Aug 2026 14:47:21 +0000, Lew Pitcher wrote:

    On Sun, 02 Aug 2026 14:17:45 +0000, Kenny McCormack wrote:

    First off, I know the "standards" answer is "Either is correct; you have no
    right to complain about anything", but I am not interested in the
    "standards" answer. If this is all you can do, then just click Next and go
    on.

    I'm interested in the "why" of why implementations might prefer one or the >>>> other.

    Consider the effects of the integer promotion rules on a system with an 8-bit
    execution characterset (CHAR_BIT == 8) that has significant characters in the
    0x80 through 0xff range[1], and how it affects the return results of functions
    like getchar(), getc(), and fgetc().
    [snip]
    [1] Not as hypothetical as you might think; Some of the earliest C compilers
    (and current compilers as well) targetted the IBM EBCDIC systems, where much
    of the basic execution characterset resides between 0x80 and 0xff, with the >>> numeric characters residing between 0xf0 and 0xf9. A signed <<char>> would >>> not work here.

    For what it's worth, this was also the reason (prior to Unicode) that C
    did not specify that alphabetic characters would have a contiguous sequence >> in the execution characterset. In EBCDIC, the alphabetics group a-i, j-r, s-z
    and A-I, J-R, S-Z, with various other characters (both assigned and unassigned)
    between the groupings.

    Unless you are payed specifically to do so I see no reason to support
    EBCDIC. Of course, IBM have enough influence to keep C standard
    as it is regarding character set, but it does not mean that anybody
    else should take is seriously.


    On the other tentacle, I believe everyone creating a C compiler for
    Commodore 64 should take PETSCII seriously; if I'm reading the Wiki-
    pedia page right, and remember the C graphic characters correctly,
    you'll need these two digraphs,

    <% for {

    %> for }

    and everything else seems to be in place; just different from ASCII
    according to

    https://www.c64os.com/post/petsciiasciiconversion

    but you're welcome to force everyone on C64s to use ASCII anyway, for
    your C compiler.


    Have a nice C64 day!
    --
    Johann | email: invalid -> com | http://www.myrkraverk.com/blog/
    I'm not from the Internet, I just work there. | via Easynews.com https://bsky.app/profile/myrkraverk.bsky.social
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From BGB@cr88192@gmail.com to comp.lang.c on Tue Aug 4 16:25:22 2026
    From Newsgroup: comp.lang.c

    On 8/4/2026 1:10 PM, Waldek Hebisch wrote:
    Lew Pitcher <lew.pitcher@digitalfreehold.ca> wrote:
    On Mon, 03 Aug 2026 14:47:21 +0000, Lew Pitcher wrote:

    On Sun, 02 Aug 2026 14:17:45 +0000, Kenny McCormack wrote:

    First off, I know the "standards" answer is "Either is correct; you have no
    right to complain about anything", but I am not interested in the
    "standards" answer. If this is all you can do, then just click Next and go
    on.

    I'm interested in the "why" of why implementations might prefer one or the >>>> other.

    Consider the effects of the integer promotion rules on a system with an 8-bit
    execution characterset (CHAR_BIT == 8) that has significant characters in the
    0x80 through 0xff range[1], and how it affects the return results of functions
    like getchar(), getc(), and fgetc().
    [snip]
    [1] Not as hypothetical as you might think; Some of the earliest C compilers
    (and current compilers as well) targetted the IBM EBCDIC systems, where much
    of the basic execution characterset resides between 0x80 and 0xff, with the >>> numeric characters residing between 0xf0 and 0xf9. A signed <<char>> would >>> not work here.

    For what it's worth, this was also the reason (prior to Unicode) that C
    did not specify that alphabetic characters would have a contiguous sequence >> in the execution characterset. In EBCDIC, the alphabetics group a-i, j-r, s-z
    and A-I, J-R, S-Z, with various other characters (both assigned and unassigned)
    between the groupings.

    Unless you are payed specifically to do so I see no reason to support
    EBCDIC. Of course, IBM have enough influence to keep C standard
    as it is regarding character set, but it does not mean that anybody
    else should take is seriously.


    Practically speaking, unless one is targeting a machine that uses EBCDIC
    or some other nonstandard character set, better advised to mostly ignore
    it, as ASCII has made a decisive win here...

    Well, and UTF-8...


    Had in my projects partly adopted Unicode, but not without fudging.

    Basic character-set mostly limited to a few blocks:
    Latin-1 range;
    Also went and added Greek and Cyrillic characters and similar.

    Except 0600..07FF: Reclaimed / Reused in 8x8 console fonts.
    Most characters in this range can't be represented in 8x8 pixels.
    Was more useful to use 0600..06FF for 00..FF dense hexadecimal.
    0..9, A..F: Can be represented nicely in 4x8 pixels.

    In some cases, it is nice to be able to display twice the hexadecimal in
    half the space (can also be used for decimal by treating it as BCD).

    Also for reasons was nicer if it could fit in the UTF-8 2-byte range.

    In this case, 0700..07FF can be used for some patterns related to UI
    drawing and representing images via color-cells.

    Say, for example (6 bits):
    Vsgn,Hsgn,Vfrq2,Hfrq2
    Which effectively specifies a sine-wave pattern at 1 of 4 frequencies
    with a sign; Both horizontal and vertical.

    This can be used to generate a series of 64 patterns that are useful in approximating images as color-cells.

    Well, then some rounded curves and dithered gradient patterns (for more
    useful image approximation); and some basic tilesets for UI elements.


    Well, some of these can be useful if one is storing graphics data in a
    form like, say:
    1b: Escape (0=Normal, 1=Skip/RLE/etc)
    7b: Cell-Index
    4b: ColorA, 16-color / RGBI
    4b: ColorB: 16-color / RGBI
    Skip might be used for blocks that are skipped over;
    RLE for blocks repeating the same pattern or a flat-color region.
    ...
    Though, not exactly high fidelity; but when it works OK, may be hard to
    beat (and can reuse text-console mechanics).

    ...


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Wed Aug 5 02:57:17 2026
    From Newsgroup: comp.lang.c

    On Tue, 4 Aug 2026 18:10:37 -0000 (UTC), Waldek Hebisch wrote:

    Unless you are payed specifically to do so I see no reason to
    support EBCDIC. Of course, IBM have enough influence to keep C
    standard as it is regarding character set, but it does not mean that
    anybody else should take is seriously.

    Interesting that IBMrCOs excuse for creating EBCDIC (for the System/360
    range) was that the ASCII standard wasnrCOt quite rCLmaturerCY enough for production use at the time.

    Given that both came out in 1964, the difference could only have been
    a few months at most.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Wed Aug 5 03:00:38 2026
    From Newsgroup: comp.lang.c

    On Tue, 4 Aug 2026 15:10:55 -0000 (UTC), Lew Pitcher wrote:

    I mentioned Unicode because it both simplifies /and/ complicates the
    matter of alphabetic value contiguity; While it ensures that
    contiguity within an alphabet, it does not ensure contiguity between alphabets (not that I think it should), leading to the same problem
    that EBCDIC presented in the first place.

    Such simplistic arithmetic-based notions of character classification
    only worked in ASCII (and related encodings) for very limited
    character sets anyway.

    The international nature of the present-day computer market forces you
    to bite the bullet and admit that proper localization handling
    requires nontrivial libraries to implement properly.

    Luckily, such libraries are widely available in the open-source world
    -- for Unicode.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@Keith.S.Thompson+u@gmail.com to comp.lang.c on Tue Aug 4 21:36:52 2026
    From Newsgroup: comp.lang.c

    antispam@fricas.org (Waldek Hebisch) writes:
    [...]
    Unless you are payed specifically to do so I see no reason to support
    EBCDIC. Of course, IBM have enough influence to keep C standard
    as it is regarding character set, but it does not mean that anybody
    else should take is seriously.

    What kind of "support" are you talking about?

    Most of the time, it's just as easy to write code that will work
    correctly regardless of the target system's character set, as long
    as the implementation is conforming. You don't need to write
    ('a' <= c && c <= 'z') when you can write islower((unsigned char)c).

    Though it can make a difference if you need to deal with multi-byte
    characters; Unicode, which is based on ASCII, is just about the only
    realistic option (I don't know that anyone actually uses UTF-EBCDIC).
    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lynn McGuire@lynnmcguire5@gmail.com to comp.lang.c on Wed Aug 5 00:19:57 2026
    From Newsgroup: comp.lang.c

    On 8/4/2026 9:57 PM, Lawrence DrCOOliveiro wrote:
    On Tue, 4 Aug 2026 18:10:37 -0000 (UTC), Waldek Hebisch wrote:

    Unless you are payed specifically to do so I see no reason to
    support EBCDIC. Of course, IBM have enough influence to keep C
    standard as it is regarding character set, but it does not mean that
    anybody else should take is seriously.

    Interesting that IBMrCOs excuse for creating EBCDIC (for the System/360 range) was that the ASCII standard wasnrCOt quite rCLmaturerCY enough for production use at the time.

    Given that both came out in 1964, the difference could only have been
    a few months at most.

    IBM probably had a hundred people working on EBCDIC for a couple of years.

    Plus, wasn't the System/360 the first 8 bit byte / 32 bit word machine?

    Lynn

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@david.brown@hesbynett.no to comp.lang.c on Wed Aug 5 09:01:06 2026
    From Newsgroup: comp.lang.c

    On 04/08/2026 17:10, Lew Pitcher wrote:
    On Mon, 03 Aug 2026 16:58:39 -0700, Keith Thompson wrote:

    Lew Pitcher <lew.pitcher@digitalfreehold.ca> writes:
    [...]
    For what it's worth, this was also the reason (prior to Unicode)
    that C did not specify that alphabetic characters would have a
    contiguous sequence in the execution characterset. In EBCDIC,
    the alphabetics group a-i, j-r, s-z and A-I, J-R, S-Z, with
    various other characters (both assigned and unassigned) between
    the groupings.

    C still doesn't require Unicode (well, mostly),

    Yes. I mentioned Unicode because it both simplifies /and/ complicates
    the matter of alphabetic value contiguity; While it ensures that contiguity within an alphabet, it does not ensure contiguity between alphabets (not
    that I think it should), leading to the same problem that EBCDIC presented
    in the first place.

    and still doesn't require 'i'+1=='j'.

    I pointed that out because it has become a common programmer misconception; hand rolled isalpha-like functions often express themselves with a range check in the form of
    is_lower_case = ((some_char >= 'a') && (some_char <= 'z'));
    is_upper_case = ((some_char >= 'A') && (some_char <= 'Z'));

    The standard explicitly requires /numeric/ characters to have contiguity, though.
    is_number = ((some_char >= '0') && (some_char <= '9'));


    C does have UTF-8 string literals, such as
    u8"hello", which are encoded as UTF-8, but ordinary string literals
    like "hello" are still encoded using the execution character set,
    which could be EBCDIC.

    There's a proposal to require 'a'..'f' and 'A'..'F' to be contiguous,
    but it hasn't appeared in the latest C2y draft.

    https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3192.pdf

    That's going to complicate the mainframe C compilers a bit :-)
    Or, as a TV presenter often put it...
    "Oh no! Anyway ..."


    No, it is not going to be an issue for any real-world character sets (including EBCDIC).

    Still, I don't think it is going to be particularly useful for anyone.
    The only purpose I can see of knowing that "A" - "F" and "a" - "f" are contiguous is for convenience when converting to and from hex
    characters. And the kind of system where you would find that useful
    (rather than just using "printf" and friends) is for small embedded
    systems. In such cases, you already know the character set, and you
    know you are not coding for a mainframe.

    So this proposal is simply documenting something you already know - even
    on mainframes and dinosaurs. There's nothing wrong with that, and it
    can be good to have things written out explicitly in the standards. But
    I don't think this particular change is going to make things easier for anyone.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Wed Aug 5 07:18:40 2026
    From Newsgroup: comp.lang.c

    On Mon, 3 Aug 2026 13:20:07 -0700, Chris M. Thomasson wrote:

    fwiw, I personally prefer unsigned char for all of my raw buffers
    and such, but that's just me.

    On the original PDP-11 (where the bulk of early Unix and C development happened), the rCLmove byte from memory to registerrCY instruction would sign-extend the byte into the 16-bit register.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Wed Aug 5 07:22:07 2026
    From Newsgroup: comp.lang.c

    On Mon, 3 Aug 2026 18:38:03 -0500, BGB wrote:

    ... (though last I checked, MSVC still doesn't fully support C99;
    eg, still no VLAs or _Complex).

    If a language implementation still doesnrCOt fully cope with a version
    of the language spec that is from over a quarter century ago and about
    two subsequent revisions out of date, I would say that describes a
    product that is on rCLlife supportrCY ...
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c,comp.sys.acorn.misc on Wed Aug 5 07:30:09 2026
    From Newsgroup: comp.lang.c

    On 04 Aug 2026 13:13:22 +0100 (BST), Theo wrote:

    Also, in that vein, you can easily merge four 8 bit values in
    registers into a 32-bit word:

    ORR Rd,Rs0,Rs1,LSL#8
    ORR Rd, Rd,Rs2,LSL#16
    ORR Rd, Rd,Rs3,LSL#24

    which sign extension would mess up (you'd have to mask off the sign
    bits first).

    ThatrCOs what happens in general: any kind of bit-twiddling is usually
    much easier with unsigned rather than signed integer types (of
    whatever size).

    I once had to do some inter-process communication between a clientrCOs
    online shop system and the payment processor. The code library they
    provided was written in Java, so I wrote a wrapper app around that to communicate with the main shop system (which I had written in C++).

    (Seasoned Java programmers can probably already guess where this story
    is going ...)

    About once a week or so, a payment would fail to go through. Took me
    quite a few examinations of debug messages before I realized that,
    because Java only has signed integers and no unsigned, I was sometimes computing a length field incorrectly due to sign extension.

    Put in the necessary masking calls, and all was hunky-dory after that.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From BGB@cr88192@gmail.com to comp.lang.c on Wed Aug 5 04:02:17 2026
    From Newsgroup: comp.lang.c

    On 8/5/2026 2:22 AM, Lawrence DrCOOliveiro wrote:
    On Mon, 3 Aug 2026 18:38:03 -0500, BGB wrote:

    ... (though last I checked, MSVC still doesn't fully support C99;
    eg, still no VLAs or _Complex).

    If a language implementation still doesnrCOt fully cope with a version
    of the language spec that is from over a quarter century ago and about
    two subsequent revisions out of date, I would say that describes a
    product that is on rCLlife supportrCY ...

    MSVC is kinda slow-burn in this way...

    Takes until 2013/2015 to start adding C99...
    2026, still doesn't fully support C99, but apparently has parts of C11
    and C17 as a consolation prize...

    I think the story was something of like:
    MS looked at how much of C99 they needed to support to build programs
    like FFmpeg and similar, and just implemented that.

    Ironically, it tends to be fairly conservative.


    Even as other parts of Windows turn into a broken vibe-coded mess
    (except for the irony that staying with Win10 partly saves one from the
    mess than Win11 has become). Well, until what point I end up needing to
    move off Win10, then probably over to Linux or something at this point.

    MS seemingly just sort of in a race to find how many ways they can shoot themselves in the foot at this point.

    ...


    Well, or in some ways, "It is the end of PCs as we know 'em ..." (well,
    set to the turn of a certain other slightly cliche'd song).

    ...


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From BGB@cr88192@gmail.com to comp.lang.c on Wed Aug 5 04:40:15 2026
    From Newsgroup: comp.lang.c

    On 8/3/2026 9:34 PM, Chris M. Thomasson wrote:
    On 8/3/2026 4:38 PM, BGB wrote:
    On 8/3/2026 4:25 PM, Chris M. Thomasson wrote:
    On 8/3/2026 2:06 PM, bart wrote:
    On 03/08/2026 21:20, Chris M. Thomasson wrote:
    On 8/2/2026 7:17 AM, Kenny McCormack wrote:
    First off, I know the "standards" answer is "Either is correct;
    you have no
    right to complain about anything", but I am not interested in the
    "standards" answer.-a If this is all you can do, then just click
    Next and go
    on.

    I'm interested in the "why" of why implementations might prefer
    one or the
    other.

    Consider:

    /* macro 'U' must be defined on the cmd line */
    #include <stdio.h>

    int main(void)
    {
    -a-a-a-a U char c = 255;

    -a-a-a-a printf("Result of 'c > 0': %d\n",c > 0);
    }

    And the following command lines:

    $ tcc -DU= -run CheckSignedChar.c
    $ tcc -DU=signed -run CheckSignedChar.c
    $ tcc -DU=unsigned -run CheckSignedChar.c

    On 32 bit RpiOS, the default is unsigned, but on x64 Ubuntu, the
    default is
    signed.-a I'm interested in what sorts of factors drive the
    decision- making.

    Note, BTW, that I first noticed this in a project using gcc, but
    it is
    easier to test using tcc, as above.

    Also, total aside, I'm surprised that one needs to do -DU= instead >>>>>> of just
    -DU.-a I thought -DU would define it as an empty string, but that >>>>>> generates
    a compile error.-a You need -DU=.-a Why?


    The sign of char is just what the underlying system needs to do its >>>>> thing. If you want a signed char, just signed char. ;^)

    It's not that simple. Very many libraries including the standard
    library make use of char* for strings for example. And string
    literals will be char* too.

    So you have to play along, you can't just use signed char* or
    unsigned char*; compilers will complain.



    I use unsigned char for my personal buffers. If a char is signed or
    not is up to the impl. C std besides the point here. If I want to use
    a C function, I know how to do it.

    I typically do:
    -a-a typedef unsigned char byte;-a-a-a //often
    -a-a typedef signed char sbyte;-a-a-a //sometimes

    I also remember using the word, word a lot... ;^)

    Not for bytes, but for things like uintptr_t. Always found it useful.

    A double word struct is comprised of two adjacent words.


    struct anchor
    {
    -a-a-a word m_part_0;
    -a-a-a word m_part_1;
    };

    make sure with a static assert or something that the sizeof(struct
    anchor) == (sizeof(word) * 2)

    Fwiw, it works well with the CMPXCH8B or CMPXCHG16B instructions on x86. Double width atomic CAS.


    There is of course:
    WORD : 16-bit
    DWORD: 32-bit
    QWORD: 64-bit

    But, then others use WORD for 32-bit, with HALF for 16-bit...
    Except then HALF becomes ambiguous if one means a 16-bit integer, or
    Binary16; ...



    Then often u16/u32/u64, s16/s32/s64, ...

    But, mostly because even with C99, "uint64_t" and similar are enough
    typing to be more annoying (whenever one feels a need for an exact-
    width type). Had started gradually shifting to using the C99 types as
    a reference point, as I am no longer actively using compilers that
    don't support the C99 "stdint.h" stuff (though last I checked, MSVC
    still doesn't fully support C99; eg, still no VLAs or _Complex).
    Its been a while since I used c99 on windows, but iirc, their (MSVC)
    support for complex numbers was total crap. I think there was a way to
    get it working, but it was not std at all. Iirc the last GCC I used had
    good support for std complex numbers in C99.

    Yeah.

    In my case, I implemented them, but they are partly implemented via the
    SIMD path internally.

    Yeah:
    complex double cx, cy, cz;
    cx = 1.0 + 2.0*I;
    cy = 3.0 + 4.0*I;
    cz = cx * cy;
    Works basically as expected.

    Promotion paths kinda look like:
    char -> short -> int -> long -> long long -> __int128.
    int -> double, long -> double
    short float -> float -> double -> long double
    float -> complex float, double -> complex double
    complex float -> __quatf, complex double -> __quatd

    Note that "complex long double" and "quaternion long double" don't
    currently exist.

    Non-default paths may exist but may internally require multiple hops.

    TBD: Should quaternions have a wrapper header and similar to better
    mimic the "complex.h" interface?...

    quaternion float qx, qy, qz;
    qx = 1.0 + 2.0*I + 3.0*J + 4.0*K;

    ?...

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@david.brown@hesbynett.no to comp.lang.c on Wed Aug 5 12:35:57 2026
    From Newsgroup: comp.lang.c

    On 05/08/2026 11:02, BGB wrote:
    On 8/5/2026 2:22 AM, Lawrence DrCOOliveiro wrote:
    On Mon, 3 Aug 2026 18:38:03 -0500, BGB wrote:

    ... (though last I checked, MSVC still doesn't fully support C99;
    eg, still no VLAs or _Complex).

    If a language implementation still doesnrCOt fully cope with a version
    of the language spec that is from over a quarter century ago and about
    two subsequent revisions out of date, I would say that describes a
    product that is on rCLlife supportrCY ...

    MSVC is kinda slow-burn in this way...

    Takes until 2013/2015 to start adding C99...
    2026, still doesn't fully support C99, but apparently has parts of C11
    and C17 as a consolation prize...

    I think the story was something of like:
    MS looked at how much of C99 they needed to support to build programs
    like FFmpeg and similar, and just implemented that.

    Ironically, it tends to be fairly conservative.


    AFAIUI (and my only reference is "things I read") MS felt that C was a
    dead language, and C++ was the way forward (along with C# and other languages). They viewed C as basically a limited version of C++, and
    thus supported the C99 features that also are part of C++. The C
    version supported by MSVC (until relatively recently) was simply the C
    subset of C++.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Johann 'Myrkraverk' Oskarsson@johann@myrkraverk.invalid to comp.lang.c on Wed Aug 5 18:49:58 2026
    From Newsgroup: comp.lang.c

    On 05/08/2026 5:02 PM, BGB wrote:
    On 8/5/2026 2:22 AM, Lawrence DrCOOliveiro wrote:
    On Mon, 3 Aug 2026 18:38:03 -0500, BGB wrote:

    ... (though last I checked, MSVC still doesn't fully support C99;
    eg, still no VLAs or _Complex).

    If a language implementation still doesnrCOt fully cope with a version
    of the language spec that is from over a quarter century ago and about
    two subsequent revisions out of date, I would say that describes a
    product that is on rCLlife supportrCY ...

    MSVC is kinda slow-burn in this way...

    Takes until 2013/2015 to start adding C99...
    2026, still doesn't fully support C99, but apparently has parts of C11
    and C17 as a consolation prize...

    I think the story was something of like:
    MS looked at how much of C99 they needed to support to build programs
    like FFmpeg and similar, and just implemented that.

    Ironically, it tends to be fairly conservative.


    Even as other parts of Windows turn into a broken vibe-coded mess
    (except for the irony that staying with Win10 partly saves one from the
    mess than Win11 has become). Well, until what point I end up needing to
    move off Win10, then probably over to Linux or something at this point.

    MS seemingly just sort of in a race to find how many ways they can shoot themselves in the foot at this point.

    In my experience, it's a race between Linux and Windows, about which one
    is worse. When I finally give up on Windows, it won't be Linux I run
    to. It'll be something else. And probably not Mac OS either. They're
    not much better than either Windows, nor Linux, as a desktop experience.


    ...


    Well, or in some ways, "It is the end of PCs as we know 'em ..." (well,
    set to the turn of a certain other slightly cliche'd song).

    ...



    It always is. Before too long, when PC gaming is dead, and companies
    are using tablets or phones instead of /thin clients/, the average "PC"
    will be the equivalent of 10,000 USD in today's money. I don't know
    when that'll happen, but the world is on the trajectory towards that
    reality, and unless that trajectory changes, my world view will become
    reality.

    So plan to get rich in the near-ish future!
    --
    Johann | email: invalid -> com | http://www.myrkraverk.com/blog/
    I'm not from the Internet, I just work there. | via Easynews.com https://bsky.app/profile/myrkraverk.bsky.social
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Johann 'Myrkraverk' Oskarsson@johann@myrkraverk.invalid to comp.lang.c on Wed Aug 5 18:57:40 2026
    From Newsgroup: comp.lang.c

    On 05/08/2026 1:19 PM, Lynn McGuire wrote:
    On 8/4/2026 9:57 PM, Lawrence DrCOOliveiro wrote:
    On Tue, 4 Aug 2026 18:10:37 -0000 (UTC), Waldek Hebisch wrote:

    Unless you are payed specifically to do so I see no reason to
    support EBCDIC. Of course, IBM have enough influence to keep C
    standard as it is regarding character set, but it does not mean that
    anybody else should take is seriously.

    Interesting that IBMrCOs excuse for creating EBCDIC (for the System/360
    range) was that the ASCII standard wasnrCOt quite rCLmaturerCY enough for
    production use at the time.

    Given that both came out in 1964, the difference could only have been
    a few months at most.

    IBM probably had a hundred people working on EBCDIC for a couple of years.

    Plus, wasn't the System/360 the first 8 bit byte / 32 bit word machine?

    Lynn


    If I remember correctly, there were several incompatible versions of the
    ASCII standard in that time frame. Before ASCII solidified, it was pro-
    bably the correct choice to ignore it. Of course, I didn't dig up
    sources, so I don't remember if ASCII was solid before or after 1964.

    I wouldn't know about the world's first 8bit byte/32bit word machine,
    but weren't there machines being developed in different countries too?

    BPCL was not invented for an American computer, yet its descendant, C
    comes from America, and is used everywhere now.


    Happy C coding in EBCDIC!
    --
    Johann | email: invalid -> com | http://www.myrkraverk.com/blog/
    I'm not from the Internet, I just work there. | via Easynews.com https://bsky.app/profile/myrkraverk.bsky.social
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From scott@scott@slp53.sl.home (Scott Lurndal) to comp.lang.c on Wed Aug 5 14:33:05 2026
    From Newsgroup: comp.lang.c

    Lynn McGuire <lynnmcguire5@gmail.com> writes:
    On 8/4/2026 9:57 PM, Lawrence DrCOOliveiro wrote:
    On Tue, 4 Aug 2026 18:10:37 -0000 (UTC), Waldek Hebisch wrote:

    Unless you are payed specifically to do so I see no reason to
    support EBCDIC. Of course, IBM have enough influence to keep C
    standard as it is regarding character set, but it does not mean that
    anybody else should take is seriously.

    Interesting that IBMrCOs excuse for creating EBCDIC (for the System/360
    range) was that the ASCII standard wasnrCOt quite rCLmaturerCY enough for
    production use at the time.

    Given that both came out in 1964, the difference could only have been
    a few months at most.

    IBM probably had a hundred people working on EBCDIC for a couple of years.

    Unlikely. IBM used 6-bit BCDIC for systems prior to the 360 family and
    it was simply logical to extend it to 8-bits and maintain compatability
    with prior generations of IBM systems.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@bc@freeuk.com to comp.lang.c on Wed Aug 5 17:20:33 2026
    From Newsgroup: comp.lang.c

    On 05/08/2026 11:18, Johann 'Myrkraverk' Oskarsson wrote:
    On 05/08/2026 3:30 PM, Lawrence DrCOOliveiro wrote:
    On 04 Aug 2026 13:13:22 +0100 (BST), Theo wrote:

    Also, in that vein, you can easily merge four 8 bit values in
    registers into a 32-bit word:

    ORR Rd,Rs0,Rs1,LSL#8
    ORR Rd, Rd,Rs2,LSL#16
    ORR Rd, Rd,Rs3,LSL#24

    which sign extension would mess up (you'd have to mask off the sign
    bits first).

    ThatrCOs what happens in general: any kind of bit-twiddling is usually
    much easier with unsigned rather than signed integer types (of
    whatever size).

    I once had to do some inter-process communication between a clientrCOs
    online shop system and the payment processor. The code library they
    provided was written in Java, so I wrote a wrapper app around that to
    communicate with the main shop system (which I had written in C++).

    (Seasoned Java programmers can probably already guess where this story
    is going ...)

    About once a week or so, a payment would fail to go through. Took me
    quite a few examinations of debug messages before I realized that,
    because Java only has signed integers and no unsigned, I was sometimes
    computing a length field incorrectly due to sign extension.


    Now, that's only because of your own inexperience at the time.-a I have
    also dealt with, and I mentioned this briefly in another post, payment processing in C.-a This was to bridge the hardware terminal with the POS software.

    I used the decNumber library for the financial transaction calculations.

    I don't begrudge people's inexperience, but why do you make it sound
    like you were using integers for the payment field?-a Did you not learn during your first semester of Java, that it's much, much better to use BigDecimal,

    -a https://docs.oracle.com/javase/8/docs/api/java/math/BigDecimal.html

    for the financial transactions?

    Adding comp.lang.java in case someone there wants to chime in.

    What not just add in all 100,000 newsgroups? In case anyone in those
    wants to comment on any of the myriad random topics and ideas you seem compelled to hit on every day?

    It's getting exhausting.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From James Kuyper@jameskuyper@alumni.caltech.edu to comp.lang.c on Wed Aug 5 13:33:44 2026
    From Newsgroup: comp.lang.c

    On 2026-08-05 03:22, Lawrence DrCOOliveiro wrote:
    On Mon, 3 Aug 2026 18:38:03 -0500, BGB wrote:

    ... (though last I checked, MSVC still doesn't fully support C99;
    eg, still no VLAs or _Complex).

    If a language implementation still doesnrCOt fully cope with a version
    of the language spec that is from over a quarter century ago and about
    two subsequent revisions out of date, I would say that describes a
    product that is on rCLlife supportrCY ...

    "cope" is fairly vague. VLAs and complex math are both optional in the
    current version of C, so lack of support for those features is no
    barrier to being a fully conforming implementation.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c on Wed Aug 5 12:36:23 2026
    From Newsgroup: comp.lang.c

    On 8/5/2026 12:22 AM, Lawrence DrCOOliveiro wrote:
    On Mon, 3 Aug 2026 18:38:03 -0500, BGB wrote:

    ... (though last I checked, MSVC still doesn't fully support C99;
    eg, still no VLAs or _Complex).

    If a language implementation still doesnrCOt fully cope with a version
    of the language spec that is from over a quarter century ago and about
    two subsequent revisions out of date, I would say that describes a
    product that is on rCLlife supportrCY ...

    MSVC is pretty good with modern C++. MSVC 6 had pretty damn good support
    for C, but teribble support for C++, iirc they licensed the dinkumware
    crap stl and shit like that. However, it seems they push C++ now and
    treat C as as a second class citizen, so to speak. Not sure if they
    support membars and atomics in C yet. I only use it for C++ nowdays.

    Iirc, a compiler that tried to adopt C11 is Pelles. Even then I found
    some issues. Fwiw, when you get some free time, read all of:

    https://forum.pellesc.de/index.php?topic=7167.msg27217#msg27217

    https://forum.pellesc.de/index.php?topic=7311.msg27764#msg27764
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c on Wed Aug 5 12:39:41 2026
    From Newsgroup: comp.lang.c

    On 8/5/2026 3:49 AM, Johann 'Myrkraverk' Oskarsson wrote:
    [...]

    Are you posting what AI wrote? Are you an AI bot? Not 100% sure, but it
    seems odd to me. Thanks.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Wed Aug 5 21:50:34 2026
    From Newsgroup: comp.lang.c

    On Wed, 5 Aug 2026 13:33:44 -0400, James Kuyper wrote:

    On 2026-08-05 03:22, Lawrence DrCOOliveiro wrote:

    On Mon, 3 Aug 2026 18:38:03 -0500, BGB wrote:

    ... (though last I checked, MSVC still doesn't fully support C99;
    eg, still no VLAs or _Complex).

    If a language implementation still doesnrCOt fully cope with a
    version of the language spec that is from over a quarter century
    ago and about two subsequent revisions out of date, I would say
    that describes a product that is on rCLlife supportrCY ...

    "cope" is fairly vague. VLAs and complex math are both optional in
    the current version of C, so lack of support for those features is
    no barrier to being a fully conforming implementation.

    Technically, you might be correct.

    But when your competition is GCC, then letting yourself look bad means
    yourCOre not even trying any more.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Wed Aug 5 21:54:53 2026
    From Newsgroup: comp.lang.c

    On Wed, 5 Aug 2026 04:02:17 -0500, BGB wrote:

    Well, until what point I end up needing to move off Win10, then
    probably over to Linux or something at this point.

    Linux is coming to you anyway (at least on Windows 11, I suppose).
    Currently you have WSL2, with a full-fat Linux kernel sitting in some
    cut-down Hyper-V bag hanging off the side of Windows. Filesystem
    performance is not the best, because that has to go through the
    Windows kernel. So WSL3 will move Windows out of the way a bit more,
    letting the Linux kernel have more direct access to its own
    filesystems.

    WSL2+ is already mandatory for an rCLAI workstationrCY setup on Windows, I expect at some point itrCOll become mandatory for regular users as well.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Wed Aug 5 21:57:56 2026
    From Newsgroup: comp.lang.c

    On Wed, 5 Aug 2026 17:20:33 +0100, bart wrote:

    On 05/08/2026 11:18, Johann 'Myrkraverk' Oskarsson wrote:

    On 05/08/2026 3:30 PM, Lawrence DrCOOliveiro wrote:

    ... I was sometimes computing a length field incorrectly due to
    sign extension.

    ... why do you make it sound like you were using integers for the
    payment field?

    What not just add in all 100,000 newsgroups? In case anyone in those
    wants to comment on any of the myriad random topics and ideas you
    seem compelled to hit on every day?

    Also, somebody didnrCOt quite read what I wrote before commenting ...
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@Keith.S.Thompson+u@gmail.com to comp.lang.c on Wed Aug 5 15:29:16 2026
    From Newsgroup: comp.lang.c

    bart <bc@freeuk.com> writes:
    [...]
    What not just add in all 100,000 newsgroups? In case anyone in those
    wants to comment on any of the myriad random topics and ideas you seem compelled to hit on every day?

    It's getting exhausting.

    The solution is left as an exercise for your killfile.

    Johann 'Myrkraverk' Oskarsson is just the latest in a long line
    of tiresome trolls who think everyone else here is Doing It Wrong
    and their own posts are more important than anyone else's, whether
    they're about C or not. He will not respond to reasonable requests
    (I tried for a while). Eventually he'll get tired and comp.lang.c
    will move on without him. Meanwhile, in my humble opinion, it's
    not worth replying to him.

    (I see that this same user posted a few times in 2019, and did not
    seem to be a troll at the time.)
    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@cross@spitfire.i.gajendra.net (Dan Cross) to comp.lang.c on Wed Aug 5 22:38:23 2026
    From Newsgroup: comp.lang.c

    In article <114uh60$2nab4$1@dont-email.me>,
    Lynn McGuire <lynnmcguire5@gmail.com> wrote:
    On 8/4/2026 9:57 PM, Lawrence DrCOOliveiro wrote:
    On Tue, 4 Aug 2026 18:10:37 -0000 (UTC), Waldek Hebisch wrote:

    Unless you are payed specifically to do so I see no reason to
    support EBCDIC. Of course, IBM have enough influence to keep C
    standard as it is regarding character set, but it does not mean that
    anybody else should take is seriously.

    Interesting that IBMrCOs excuse for creating EBCDIC (for the System/360
    range) was that the ASCII standard wasnrCOt quite rCLmaturerCY enough for
    production use at the time.

    Given that both came out in 1964, the difference could only have been
    a few months at most.

    IBM probably had a hundred people working on EBCDIC for a couple of years.

    Plus, wasn't the System/360 the first 8 bit byte / 32 bit word machine?

    I don't know if it was the first, but it was certainly the first
    _successful_ machine with those properties. As the tale goes,
    Fred Brooks kicked Gene Amdahl out of his office and told him
    not to come back until he had power-of-two data sizes.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lynn McGuire@lynnmcguire5@gmail.com to comp.lang.c on Wed Aug 5 18:30:22 2026
    From Newsgroup: comp.lang.c

    On 8/2/2026 9:17 AM, Kenny McCormack wrote:
    First off, I know the "standards" answer is "Either is correct; you have no right to complain about anything", but I am not interested in the
    "standards" answer. If this is all you can do, then just click Next and go on.

    I'm interested in the "why" of why implementations might prefer one or the other.

    Consider:

    /* macro 'U' must be defined on the cmd line */
    #include <stdio.h>

    int main(void)
    {
    U char c = 255;

    printf("Result of 'c > 0': %d\n",c > 0);
    }

    And the following command lines:

    $ tcc -DU= -run CheckSignedChar.c
    $ tcc -DU=signed -run CheckSignedChar.c
    $ tcc -DU=unsigned -run CheckSignedChar.c

    On 32 bit RpiOS, the default is unsigned, but on x64 Ubuntu, the default is signed. I'm interested in what sorts of factors drive the decision-making.

    Note, BTW, that I first noticed this in a project using gcc, but it is
    easier to test using tcc, as above.

    Also, total aside, I'm surprised that one needs to do -DU= instead of just -DU. I thought -DU would define it as an empty string, but that generates
    a compile error. You need -DU=. Why?

    So, you have to check every compiler and every compiler version to see
    what the signedness of char is. That is not good in these days of UTF-8.

    Lynn

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@Keith.S.Thompson+u@gmail.com to comp.lang.c on Wed Aug 5 16:41:36 2026
    From Newsgroup: comp.lang.c

    Lynn McGuire <lynnmcguire5@gmail.com> writes:
    [...]
    So, you have to check every compiler and every compiler version to see
    what the signedness of char is. That is not good in these days of
    UTF-8.

    Not really. You can usually write code that doesn't care whether
    plain char is signed or unsigned. And if it matters, you can check
    whether CHAR_MIN==0.

    This evolved from systems like the PDP-11 where character values
    ranged from 0 to 127, so the signedness of plain char didn't
    matter much.

    It's annoying that, in many implementations, UTF-8 strings can
    contain elements with negative values (negative character values
    rarely make sense), but in practice it doesn't cause many problems.

    IMHO it would be cleaner to require plain char to be unsigned,
    but I don't see that happening.
    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From antispam@antispam@fricas.org (Waldek Hebisch) to comp.lang.c on Thu Aug 6 00:21:42 2026
    From Newsgroup: comp.lang.c

    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
    antispam@fricas.org (Waldek Hebisch) writes:
    [...]
    Unless you are payed specifically to do so I see no reason to support
    EBCDIC. Of course, IBM have enough influence to keep C standard
    as it is regarding character set, but it does not mean that anybody
    else should take is seriously.

    What kind of "support" are you talking about?

    Most of the time, it's just as easy to write code that will work
    correctly regardless of the target system's character set, as long
    as the implementation is conforming. You don't need to write
    ('a' <= c && c <= 'z') when you can write islower((unsigned char)c).

    The two are not that same: assuming ASCII based encoding first
    detects ASCII lowercase letter, the second is locale dependent.
    In my use cases the second is usually wrong, so the first is
    better.

    Though it can make a difference if you need to deal with multi-byte characters; Unicode, which is based on ASCII, is just about the only realistic option (I don't know that anyone actually uses UTF-EBCDIC).

    --
    Waldek Hebisch
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@bc@freeuk.com to comp.lang.c on Thu Aug 6 01:24:51 2026
    From Newsgroup: comp.lang.c

    On 06/08/2026 00:41, Keith Thompson wrote:
    Lynn McGuire <lynnmcguire5@gmail.com> writes:
    [...]
    So, you have to check every compiler and every compiler version to see
    what the signedness of char is. That is not good in these days of
    UTF-8.

    Not really. You can usually write code that doesn't care whether
    plain char is signed or unsigned. And if it matters, you can check
    whether CHAR_MIN==0.

    It causes a problem here when char is signed:

    int counts[256];

    void scanstr(char* s) {
    while (*s) ++counts[*s++];
    }

    int main(void) {
    scanstr("abcdef re4");
    }

    Changing the type to 'unsigned char*', or uint_8, would result in warnings.

    IMHO it would be cleaner to require plain char to be unsigned,
    but I don't see that happening.

    Some existing programs will make assumptions about it.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@Keith.S.Thompson+u@gmail.com to comp.lang.c on Wed Aug 5 17:46:38 2026
    From Newsgroup: comp.lang.c

    bart <bc@freeuk.com> writes:
    On 06/08/2026 00:41, Keith Thompson wrote:
    Lynn McGuire <lynnmcguire5@gmail.com> writes:
    [...]
    So, you have to check every compiler and every compiler version to see
    what the signedness of char is. That is not good in these days of
    UTF-8.

    Not really. You can usually write code that doesn't care whether
    plain char is signed or unsigned. And if it matters, you can check
    whether CHAR_MIN==0.

    It causes a problem here when char is signed:

    int counts[256];

    void scanstr(char* s) {
    while (*s) ++counts[*s++];
    }

    int main(void) {
    scanstr("abcdef re4");
    }

    Changing the type to 'unsigned char*', or uint_8, would result in warnings.

    Yes, I did say "usually".

    Rather than changing the type, I'd cast the value of *s++ to
    unsigned char. (I'd also use UCHAR_MAX+1 rather than 256, more
    for clarity than for portability.)

    (Ideally, you could also use u8"abcdef re4" rather than "abcdef re4",
    but strangely enough the type of u8"..." string literals changed
    between C17 and C23. UTF-8 string literals were introduced in C99.
    From C99 to C17, the array elements have type char. In C23, they
    have type char8_t, which is the same as unsigned char; char8_t
    didn't exist in C17 and earlier.)

    IMHO it would be cleaner to require plain char to be unsigned,
    but I don't see that happening.

    Some existing programs will make assumptions about it.

    Which is why I don't see it happening. There's too much existing code
    that makes the non-portable assumption that plain char is signed.
    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@david.brown@hesbynett.no to comp.lang.c on Thu Aug 6 10:34:48 2026
    From Newsgroup: comp.lang.c

    On 05/08/2026 23:50, Lawrence DrCOOliveiro wrote:
    On Wed, 5 Aug 2026 13:33:44 -0400, James Kuyper wrote:

    On 2026-08-05 03:22, Lawrence DrCOOliveiro wrote:

    On Mon, 3 Aug 2026 18:38:03 -0500, BGB wrote:

    ... (though last I checked, MSVC still doesn't fully support C99;
    eg, still no VLAs or _Complex).

    If a language implementation still doesnrCOt fully cope with a
    version of the language spec that is from over a quarter century
    ago and about two subsequent revisions out of date, I would say
    that describes a product that is on rCLlife supportrCY ...

    "cope" is fairly vague. VLAs and complex math are both optional in
    the current version of C, so lack of support for those features is
    no barrier to being a fully conforming implementation.

    Technically, you might be correct.

    But when your competition is GCC, then letting yourself look bad means yourCOre not even trying any more.

    I don't think MS sees gcc as a competitor in this sense. I suspect that
    there are few programmers who want to use MSVC for C programming but
    choose gcc on Windows because of its support for _Complex or VLAs.

    I also think there are not many C programmers who use _Complex types -
    they are simply not useful in most coding. And programmers who do need complex numbers may well be choosing other languages anyway. (Of course
    "not many C programmers" does not mean /no/ C programmers,)

    VLAs are also not very common in C programming, and what is found is
    often arrays that are technically VLAs, but in practice are sizes that
    are known at compile time - the size is given by a variable (that is, or
    could be, declared "const") that is fixed. In C++, such "const"
    variables can be used as the size of an array - these are normal arrays
    in C++, but technically VLAs in C. MSVC users can get that by compiling
    their C code as C++, which is something I have seen MSVC users do
    without realising it.

    It would be best, of course, if MS simply added these C99 features to
    their C compiler. I do not think it is beyond their technical abilities
    or that it would be a huge effort. (It doesn't need to be particularly efficient.)

    Making VLAs and _Complex optional in C11 was, I think, a mistake. It is
    fair enough to make /new/ features optional in a new standard - and then perhaps make them required features in later standards if they are
    popular enough. I don't know if MS was instrumental in changing VLAs
    and _Complex to optional features in C11, but it certainly gives that impression.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From BGB@cr88192@gmail.com to comp.lang.c on Thu Aug 6 04:49:23 2026
    From Newsgroup: comp.lang.c

    On 8/5/2026 4:54 PM, Lawrence DrCOOliveiro wrote:
    On Wed, 5 Aug 2026 04:02:17 -0500, BGB wrote:

    Well, until what point I end up needing to move off Win10, then
    probably over to Linux or something at this point.

    Linux is coming to you anyway (at least on Windows 11, I suppose).
    Currently you have WSL2, with a full-fat Linux kernel sitting in some cut-down Hyper-V bag hanging off the side of Windows. Filesystem
    performance is not the best, because that has to go through the
    Windows kernel. So WSL3 will move Windows out of the way a bit more,
    letting the Linux kernel have more direct access to its own
    filesystems.

    WSL2+ is already mandatory for an rCLAI workstationrCY setup on Windows, I expect at some point itrCOll become mandatory for regular users as well.

    If I need to move off of Win10, will probably just go over to Debian or something...

    Not yet to the stage of downloading or burning an ISO yet though.


    Not inclined to go over to the trash fire that Windows 11 has become
    now, it does not bode well for the future of the platform.

    Even then, my current Windows 10 install was originally an auto-upgrade
    from Windows 7.

    Like, this particular "ship of PC'ous" going back to roughly the start
    of the Windows 7 era.


    Well, after I jumped over to Win7 from XP-X64 (which personally I found
    less bad than Vista).

    So, yeah:
    Vista, Win8, and Win11: MS's tendency to release turds...
    Windows 11 being an even worse turd than usual.


    I am admittedly skeptical of the whole "AI PC" thing, likewise for
    people trying to now sell "PCs" based on repurposed cellphone parts.
    Like, it seems like they are trying to take some of the downsides of cellphones (lack of user freedom, not being user upgradeable, ... and
    trying to pass them off as PCs). Like, if the thing has a 256GB eMMC and prominently shows a OneDrive logo like it was a feature, I don't want it...

    ...


    I am annoyed enough as-is in the lack of personal freedoms with a
    cellphone, the crap lifespan of the LiPo batteries, ...

    Kinda wishing someone would make something more like a RasPi in
    cellphone form and maybe used 10440 cells or something (would tolerate a little extra bulk just to be rid of the LiPo hassles).

    Well, or 14500 cells, or maybe 18650's, but this is maybe a little too
    much bulk.

    Would be kinda funny though if a person 3D printed a modified cellphone
    case and made a mod to use an 18650 in place of the LiPo. Phone is now
    like an inch thick, but no big deal... Something like 4x 10440 would be
    closer to the original form factor though (and, if the 10440's start
    going dead, one can yank and replace them easily enough, and a lot
    cheaper than the phone LiPo's).

    Though, 18650s seem to be the easiest size to find at the moment (well,
    and also IRL I have a bunch of salvaged 18650's on-hand as well; though
    mostly LiFePO4 and Na-Ion, which are 3.2V vs 3.7V), even if a bit large.


    Would also be nice to have fully unlocked software though. Should
    ideally be able to install Linux or something, and then upgrade the
    thing via "apt" or similar (and also maybe run the OS off an SDcard
    sorta like the RasPi).


    Annoyingly, can't just build something custom and still have it be able
    to function as a phone. Well, I guess, technically the task gets easier
    if it doesn't need to interface with the cell network. I guess it is a question then if there is some other viable option for wireless internet (well, besides WiFi).


    ...


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Johann 'Myrkraverk' Oskarsson@johann@myrkraverk.invalid to comp.lang.c on Thu Aug 6 20:15:32 2026
    From Newsgroup: comp.lang.c

    On 06/08/2026 3:39 AM, Chris M. Thomasson wrote:
    On 8/5/2026 3:49 AM, Johann 'Myrkraverk' Oskarsson wrote:
    [...]

    Are you posting what AI wrote? Are you an AI bot? Not 100% sure, but it seems odd to me. Thanks.

    You're just jealous because you can't write coherent prose. Nor poetry.
    You should join a poetry club, as you might learn something.

    I don't write like an A.I. Nor L.L.M. It goes the other way around.
    They -- for some value of /they/ -- write like me. /They/ got trained
    on the best of us. And I was already a great writer before the L.L.M. revolution started.

    It just happens that I wasn't famous like Stephen King before now, so
    you can waddle in error and confusion about the difference between fan-
    tasy and reality. And how to hyphenate English. I never learned the
    rules.

    I know all of this seems magical to you, but trust in the magic, and
    have faith in our saint, Dennis M. Ritchie. And please, once you have
    enough faith in the magic, start to write your own C compiler. You also
    might learn something from that!
    --
    Johann | email: invalid -> com | http://www.myrkraverk.com/blog/
    I'm not from the Internet, I just work there. | via Easynews.com https://bsky.app/profile/myrkraverk.bsky.social | for ( ;; ) _:;
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@bc@freeuk.com to comp.lang.c on Thu Aug 6 15:05:46 2026
    From Newsgroup: comp.lang.c

    On 06/08/2026 13:15, Johann 'Myrkraverk' Oskarsson wrote:
    On 06/08/2026 3:39 AM, Chris M. Thomasson wrote:
    On 8/5/2026 3:49 AM, Johann 'Myrkraverk' Oskarsson wrote:
    [...]

    Are you posting what AI wrote? Are you an AI bot? Not 100% sure, but
    it seems odd to me. Thanks.

    You're just jealous because you can't write coherent prose.-a Nor poetry.
    You should join a poetry club, as you might learn something.

    You seem to like engaging with likely machine-generated posts from
    'Ross', 'Mild', 'Chang'.


    I don't write like an A.I.-a Nor L.L.M.

    You write like those in continuously jumping to one irrelevant topic to another like some child with ADHD, rather than a mature adult.

    It would be a miracle if you started just one serious thread (preferable
    on a topic relevant to this forum), that you were genuinely interested
    in, /kept on that topic/ for more that one post.


    It just happens that I wasn't famous like Stephen King before now, so
    you can waddle in error and confusion about the difference between fan-
    tasy and reality.-a And how to hyphenate English.-a I never learned the rules.

    I know all of this seems magical to you, but trust in the magic, and
    have faith in our saint, Dennis M. Ritchie.-a And please, once you have enough faith in the magic, start to write your own C compiler.-a You also might learn something from that!

    You might try it yourself; it'll keep you too busy to keep posting
    random nonsense.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From scott@scott@slp53.sl.home (Scott Lurndal) to comp.lang.c on Thu Aug 6 14:40:44 2026
    From Newsgroup: comp.lang.c

    Lynn McGuire <lynnmcguire5@gmail.com> writes:
    On 8/2/2026 9:17 AM, Kenny McCormack wrote:
    First off, I know the "standards" answer is "Either is correct; you have no >> right to complain about anything", but I am not interested in the
    "standards" answer. If this is all you can do, then just click Next and go >> on.

    I'm interested in the "why" of why implementations might prefer one or the >> other.

    Consider:

    /* macro 'U' must be defined on the cmd line */
    #include <stdio.h>

    int main(void)
    {
    U char c = 255;

    printf("Result of 'c > 0': %d\n",c > 0);
    }

    And the following command lines:

    $ tcc -DU= -run CheckSignedChar.c
    $ tcc -DU=signed -run CheckSignedChar.c
    $ tcc -DU=unsigned -run CheckSignedChar.c

    On 32 bit RpiOS, the default is unsigned, but on x64 Ubuntu, the default is >> signed. I'm interested in what sorts of factors drive the decision-making. >>
    Note, BTW, that I first noticed this in a project using gcc, but it is
    easier to test using tcc, as above.

    Also, total aside, I'm surprised that one needs to do -DU= instead of just >> -DU. I thought -DU would define it as an empty string, but that generates >> a compile error. You need -DU=. Why?

    So, you have to check every compiler and every compiler version to see
    what the signedness of char is.

    No. It's really simple, just specify which you need (unsigned char or signed char)
    directly. Don't rely on unspecified behavior.

    Personally, I use uint8_t or int8_t depending on the use case.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Johann 'Myrkraverk' Oskarsson@johann@myrkraverk.invalid to comp.lang.c on Thu Aug 6 23:16:06 2026
    From Newsgroup: comp.lang.c

    On 06/08/2026 10:05 PM, bart wrote:
    On 06/08/2026 13:15, Johann 'Myrkraverk' Oskarsson wrote:
    On 06/08/2026 3:39 AM, Chris M. Thomasson wrote:
    On 8/5/2026 3:49 AM, Johann 'Myrkraverk' Oskarsson wrote:
    [...]

    Are you posting what AI wrote? Are you an AI bot? Not 100% sure, but
    it seems odd to me. Thanks.

    You're just jealous because you can't write coherent prose.-a Nor poetry.
    You should join a poetry club, as you might learn something.

    You seem to like engaging with likely machine-generated posts from
    'Ross', 'Mild', 'Chang'.

    Dear bart,

    You seem to be unable to keep up with long form discussions. Please go
    back to discord, where a single line comment is all that's required to
    gain /internet points/.



    I don't write like an A.I.-a Nor L.L.M.

    You write like those in continuously jumping to one irrelevant topic to another like some child with ADHD, rather than a mature adult.

    It would be a miracle if you started just one serious thread (preferable
    on a topic relevant to this forum), that you were genuinely interested
    in, /kept on that topic/ for more that one post.

    You must be an L.L.M., because you're unable to keep up with real life discussions. When people discuss things in real life, they flit from
    topic to topic, like butterflies on threads.

    Since you're unable to deal with such discussion techniques, you must
    suffer from L.L.M. stochastically generated text, and should see a
    therapist about it.



    It just happens that I wasn't famous like Stephen King before now, so
    you can waddle in error and confusion about the difference between fan-
    tasy and reality.-a And how to hyphenate English.-a I never learned the
    rules.

    I know all of this seems magical to you, but trust in the magic, and
    have faith in our saint, Dennis M. Ritchie.-a And please, once you have
    enough faith in the magic, start to write your own C compiler.-a You also
    might learn something from that!

    You might try it yourself; it'll keep you too busy to keep posting
    random nonsense.



    But this random nonsense has a purpose. It's annoying you.

    Please continue to be annoyed!
    --
    Johann | email: invalid -> com | http://www.myrkraverk.com/blog/
    I'm not from the Internet, I just work there. | via Easynews.com https://bsky.app/profile/myrkraverk.bsky.social | for ( ;; ) _:;
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@david.brown@hesbynett.no to comp.lang.c on Thu Aug 6 20:10:27 2026
    From Newsgroup: comp.lang.c

    On 06/08/2026 16:05, bart wrote:
    On 06/08/2026 13:15, Johann 'Myrkraverk' Oskarsson wrote:
    On 06/08/2026 3:39 AM, Chris M. Thomasson wrote:
    On 8/5/2026 3:49 AM, Johann 'Myrkraverk' Oskarsson wrote:
    [...]

    Are you posting what AI wrote? Are you an AI bot? Not 100% sure, but
    it seems odd to me. Thanks.

    You're just jealous because you can't write coherent prose.-a Nor poetry.
    You should join a poetry club, as you might learn something.

    You seem to like engaging with likely machine-generated posts from
    'Ross', 'Mild', 'Chang'.


    I don't write like an A.I.-a Nor L.L.M.

    You write like those in continuously jumping to one irrelevant topic to another like some child with ADHD, rather than a mature adult.

    It would be a miracle if you started just one serious thread (preferable
    on a topic relevant to this forum), that you were genuinely interested
    in, /kept on that topic/ for more that one post.


    It is unlikely to happen - I think there is no hope in appealing to any
    common human decency in that poster (or the other three you mentioned).
    He's an obnoxious idiot with delusions of grandeur - his belief in his
    writing abilities are laughable. The reason we can tell that he is not
    an AI is that no AI model would have as poor grammar as he has.

    We just have to ignore him, and eventually he'll wander off to annoy
    someone else. I just hope none of the regulars in this group get chased
    away by these trolls.


    It just happens that I wasn't famous like Stephen King before now, so
    you can waddle in error and confusion about the difference between fan-
    tasy and reality.-a And how to hyphenate English.-a I never learned the
    rules.

    I know all of this seems magical to you, but trust in the magic, and
    have faith in our saint, Dennis M. Ritchie.-a And please, once you have
    enough faith in the magic, start to write your own C compiler.-a You also
    might learn something from that!

    You might try it yourself; it'll keep you too busy to keep posting
    random nonsense.



    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@Keith.S.Thompson+u@gmail.com to comp.lang.c on Thu Aug 6 15:33:43 2026
    From Newsgroup: comp.lang.c

    scott@slp53.sl.home (Scott Lurndal) writes:
    Lynn McGuire <lynnmcguire5@gmail.com> writes:
    [...]
    So, you have to check every compiler and every compiler version to see >>what the signedness of char is.

    No. It's really simple, just specify which you need (unsigned char or
    signed char) directly. Don't rely on unspecified behavior.

    Personally, I use uint8_t or int8_t depending on the use case.

    That can be a good approach in some cases, but char, signed char,
    and unsigned char are distinct types, and there are cases where
    you have to use plain char. Functions in <string.h> operate on
    array of plain char -- and sometimes specify unsigned semantics.
    For example, strcmp() operates on arrays of char, but treats them
    as unsigned char.

    Yeah, it's a bit of a mess.

    There are (rare) occasions where you need to know whether plain
    char is signed or unsigned. Fortunately, that's easy enough to
    determine in code, even in the preprocessor.
    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@cross@spitfire.i.gajendra.net (Dan Cross) to comp.lang.c on Thu Aug 6 22:57:24 2026
    From Newsgroup: comp.lang.c

    In article <1150hng$3dds0$1@kst.eternal-september.org>,
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
    Lynn McGuire <lynnmcguire5@gmail.com> writes:
    [...]
    So, you have to check every compiler and every compiler version to see
    what the signedness of char is. That is not good in these days of
    UTF-8.

    Not really. You can usually write code that doesn't care whether
    plain char is signed or unsigned. And if it matters, you can check
    whether CHAR_MIN==0.

    This evolved from systems like the PDP-11 where character values
    ranged from 0 to 127, so the signedness of plain char didn't
    matter much.

    I'd phrase that slightly differently; on systmes like the PDP-11
    that used the 7-bit US-ASCII character set (sorry, Europeans),
    the signedness of `char` was irrelevant for handling character
    data.

    The issue arises because early C did not define a generic
    byte-sized integer type separate from `char`, so `char` got
    overloaded to serve as a "very small `int`" in lots of places.

    The situation got somewhat better when `<stdint.h>` was
    introduced, but by then the die was cast.

    It's annoying that, in many implementations, UTF-8 strings can
    contain elements with negative values (negative character values
    rarely make sense), but in practice it doesn't cause many problems.

    IMHO it would be cleaner to require plain char to be unsigned,
    but I don't see that happening.

    The cleanest thing would be to define `char` to be,
    specifically, a type designated to hold only character data,
    with a corresponding `int` type with the usual signed and
    unsigned variants, and explicit conversion functions to
    translate between `char` and the underlying representation.

    But that ain't happenin'; all the reasons you outlined for
    changing the signedness of `char` among them.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@cross@spitfire.i.gajendra.net (Dan Cross) to comp.lang.c on Thu Aug 6 22:59:15 2026
    From Newsgroup: comp.lang.c

    In article <1150k8j$3ebfi$1@dont-email.me>, bart <bc@freeuk.com> wrote:
    On 06/08/2026 00:41, Keith Thompson wrote:
    Lynn McGuire <lynnmcguire5@gmail.com> writes:
    [...]
    So, you have to check every compiler and every compiler version to see
    what the signedness of char is. That is not good in these days of
    UTF-8.

    Not really. You can usually write code that doesn't care whether
    plain char is signed or unsigned. And if it matters, you can check
    whether CHAR_MIN==0.

    It causes a problem here when char is signed:

    int counts[256];

    void scanstr(char* s) {
    while (*s) ++counts[*s++];
    }

    int main(void) {
    scanstr("abcdef re4");
    }

    Changing the type to 'unsigned char*', or uint_8, would result in warnings.

    Cast the value when using as the index:

    while (*s) ++counts[(unsignd char)*s++];

    Note that this is already required for the `is*` functions
    defined in `ctype.h` (except, IIRC, `isascii`).

    IMHO it would be cleaner to require plain char to be unsigned,
    but I don't see that happening.

    Some existing programs will make assumptions about it.

    *Many.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Fri Aug 7 00:10:47 2026
    From Newsgroup: comp.lang.c

    On Thu, 6 Aug 2026 04:49:23 -0500, BGB wrote:

    If I need to move off of Win10, will probably just go over to Debian
    or something...

    You have lots of choice. Want something rock-solid but boring? Or
    something that gets updated more frequently, just to keep life
    interesting? Want to build everything yourself from source (right down
    to the kernel), with compiler options tuned to your particular
    hardware setup? Or will generic prebuilt binaries suit you fine?

    And donrCOt feel that your choice, once made, is irrevocable. rCLDistro-hoppingrCY is a real thing in the Linux world. And if you keep
    your user files on a separate partition from the OS, you can switch OS installations without having to copy your user files around.

    I am admittedly skeptical of the whole "AI PC" thing ...

    YourCOre not alone.

    ... likewise for people trying to now sell "PCs" based on repurposed cellphone parts.

    That was the initial buzz around ApplerCOs MacBook Neo, which seemed
    like a good deal at its original price. I think a lot of the
    excitement has died down after the inevitable price rise. And the
    hardware limitations have become more obvious.

    Kinda wishing someone would make something more like a RasPi in
    cellphone form and maybe used 10440 cells or something (would
    tolerate a little extra bulk just to be rid of the LiPo hassles).

    Here <https://www.raspberrypi.com/news/piphone-home-made-raspberry-pi-smartphone/> is an old project along those lines.

    The rule seems to be: rCLif you can think of it, somebody has probably
    already tried to do it with a Raspberry PirCY. ;)

    Would also be nice to have fully unlocked software though.

    You can get builds of open-source Android that give you full control.
    Without the Google parts, of course.

    Remember that guy who self-destructed his phone rather than giving
    access to the authorities while entering the US a few weeks ago? His
    phone was running GrapheneOS.

    Annoyingly, can't just build something custom and still have it be
    able to function as a phone. Well, I guess, technically the task
    gets easier if it doesn't need to interface with the cell network.

    There are even open-source implementations of the cellphone tower
    protocols, so I think all this is possible nowadays, it just takes
    some hardware skills (which I donrCOt have) ...
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@Keith.S.Thompson+u@gmail.com to comp.lang.c on Thu Aug 6 18:23:29 2026
    From Newsgroup: comp.lang.c

    cross@spitfire.i.gajendra.net (Dan Cross) writes:
    In article <1150hng$3dds0$1@kst.eternal-september.org>,
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
    Lynn McGuire <lynnmcguire5@gmail.com> writes:
    [...]
    So, you have to check every compiler and every compiler version to see
    what the signedness of char is. That is not good in these days of
    UTF-8.

    Not really. You can usually write code that doesn't care whether
    plain char is signed or unsigned. And if it matters, you can check
    whether CHAR_MIN==0.

    This evolved from systems like the PDP-11 where character values
    ranged from 0 to 127, so the signedness of plain char didn't
    matter much.

    I'd phrase that slightly differently; on systmes like the PDP-11
    that used the 7-bit US-ASCII character set (sorry, Europeans),
    the signedness of `char` was irrelevant for handling character
    data.

    The issue arises because early C did not define a generic
    byte-sized integer type separate from `char`, so `char` got
    overloaded to serve as a "very small `int`" in lots of places.

    The situation got somewhat better when `<stdint.h>` was
    introduced, but by then the die was cast.

    Agreed, good clarification.

    It's annoying that, in many implementations, UTF-8 strings can
    contain elements with negative values (negative character values
    rarely make sense), but in practice it doesn't cause many problems.

    IMHO it would be cleaner to require plain char to be unsigned,
    but I don't see that happening.

    The cleanest thing would be to define `char` to be,
    specifically, a type designated to hold only character data,
    with a corresponding `int` type with the usual signed and
    unsigned variants, and explicit conversion functions to
    translate between `char` and the underlying representation.

    Other than requiring explicit conversions, that's pretty much what we
    have now. signed char and unsigned char are the two standard integer
    types, probably narrower than signed short and unsigned short.
    char is a special case, "designated to hold only character data",
    though that designation is not enforced.

    If it were practical, I'd like to see the "char" type either
    unsigned, or for its signedness to be irrelevant (i.e., not an
    integer type).

    (Ada, for example, defines Character as an enumeration type, and
    allows character constants as enumeration constants.)

    But that ain't happenin'; all the reasons you outlined for
    changing the signedness of `char` among them.

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

    cross@spitfire.i.gajendra.net (Dan Cross) writes:
    [...]
    Cast the value when using as the index:

    while (*s) ++counts[(unsignd char)*s++];

    Note that this is already required for the `is*` functions
    defined in `ctype.h` (except, IIRC, `isascii`).

    isascii() is not defined by ISO C, or even by POSIX. isblank() is
    another common extension. For implementations that support them,
    I don't think they're handled differently from the other is*()
    functions. Most implementations handle values from SCHAR_MIN to
    UCHAR_MAX without error, but the behavior is undefined for any
    value other than EOF outside the range 0..UCHAR_MAX.

    [...]
    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@david.brown@hesbynett.no to comp.lang.c on Fri Aug 7 09:56:30 2026
    From Newsgroup: comp.lang.c

    On 07/08/2026 02:10, Lawrence DrCOOliveiro wrote:
    On Thu, 6 Aug 2026 04:49:23 -0500, BGB wrote:

    If I need to move off of Win10, will probably just go over to Debian
    or something...

    You have lots of choice. Want something rock-solid but boring? Or
    something that gets updated more frequently, just to keep life
    interesting? Want to build everything yourself from source (right down
    to the kernel), with compiler options tuned to your particular
    hardware setup? Or will generic prebuilt binaries suit you fine?

    And donrCOt feel that your choice, once made, is irrevocable. rCLDistro-hoppingrCY is a real thing in the Linux world. And if you keep
    your user files on a separate partition from the OS, you can switch OS installations without having to copy your user files around.


    You can also use tools like DistroBox / DistroShelf (or lower-level lxc containers) to have different Linux distros running within your main
    Linux system in a light-weight manner with a shared kernel. For many
    distros, you can easily choose different desktops (Gnome, KDE, Mate,
    etc.) if you want to change the look and feel of the gui without too
    much effort - though it can be hard to keep a consistent look if that's important to you.

    And of course you have the option of full virtualisation - VirtualBox or KVM/QEMU. The cost of that is memory - which is unfortunately more of a real-world cost than it used to be.

    I am admittedly skeptical of the whole "AI PC" thing ...

    YourCOre not alone.


    Indeed. For most purposes, making the PC "AI" is just a way of making
    the CPU cost a great deal more without being any better at other tasks.
    It's fine that those that want to do AI stuff can get machines that are
    suited for the task - just like it's fine that those who want fast
    graphics can get appropriate machines. But I don't need AI acceleration
    (or fancy graphics) for development machines, small servers, laptops, or
    other machines, and it bugs me that processor manufacturers and PC
    builders push "AI" so hard, along with its costs.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@cross@spitfire.i.gajendra.net (Dan Cross) to comp.lang.c on Fri Aug 7 11:02:19 2026
    From Newsgroup: comp.lang.c

    In article <1153hcv$ba35$1@kst.eternal-september.org>,
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote: >cross@spitfire.i.gajendra.net (Dan Cross) writes:
    [...]
    Cast the value when using as the index:

    while (*s) ++counts[(unsignd char)*s++];

    Note that this is already required for the `is*` functions
    defined in `ctype.h` (except, IIRC, `isascii`).

    isascii() is not defined by ISO C, or even by POSIX.

    Ah, right you are. `isascii` was marked obsolescent in POSIX
    Issue 7 (2018) and removed in Issue 8 (2024); it never made it
    into standardized C, and was dropped during the initial work
    leading up to ANSI C (the C89 rationale discusses it), though it
    remains broadly implemented, presumably for compatibility with
    older code.

    isblank() is
    another common extension. For implementations that support them,
    I don't think they're handled differently from the other is*()
    functions. Most implementations handle values from SCHAR_MIN to
    UCHAR_MAX without error, but the behavior is undefined for any
    value other than EOF outside the range 0..UCHAR_MAX.

    Before removal from POSIX, `isascii` was specified as defined
    for all integer values. https://pubs.opengroup.org/onlinepubs/9699919799/functions/isascii.html

    I imagine that `isblank` would be implemented similarly to the
    others, however.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@cross@spitfire.i.gajendra.net (Dan Cross) to comp.lang.c on Fri Aug 7 11:47:27 2026
    From Newsgroup: comp.lang.c

    In article <1153c2h$9tat$1@kst.eternal-september.org>,
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote: >cross@spitfire.i.gajendra.net (Dan Cross) writes:
    In article <1150hng$3dds0$1@kst.eternal-september.org>,
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
    [snip]
    IMHO it would be cleaner to require plain char to be unsigned,
    but I don't see that happening.

    The cleanest thing would be to define `char` to be,
    specifically, a type designated to hold only character data,
    with a corresponding `int` type with the usual signed and
    unsigned variants, and explicit conversion functions to
    translate between `char` and the underlying representation.

    Other than requiring explicit conversions, that's pretty much what we
    have now. signed char and unsigned char are the two standard integer
    types, probably narrower than signed short and unsigned short.

    It is close, indeed, though I would argue that the implicit
    conversions can cause some minor grief. The need to cast
    arguments to `is*` feels superfluous. In the big scheme of
    things it's not a huge deal, of course, but still ugly.

    char is a special case, "designated to hold only character data",
    though that designation is not enforced.

    I'm not even sure that was the original intent. Sure, `char`
    was (and is) useful for holding character data, but I believe it
    was always intended as the byte integer type; it was probably
    just _most often_ used for representing character data. I think
    they didn't want to make it separate from other integer types
    because they felt it was "good enough" and didn't want to add
    another reserved word to the language (and what would it be?).

    This business with signed vs unsigned `char` is just historical
    baggage because for the first decade or so of C's existence,
    they didn't have to care.

    If it were practical, I'd like to see the "char" type either
    unsigned, or for its signedness to be irrelevant (i.e., not an
    integer type).

    Agreed. It shouldn't be an integer type.

    (Ada, for example, defines Character as an enumeration type, and
    allows character constants as enumeration constants.)

    Even Pascal's `Char` type is distinct from the usual integer
    types, with `chr` and `ord` operators to convert to and from.

    Not to beat the Rust drum again, but I think they came up with
    a fairly nice abstraction: an instance of the `char` type is a
    multibyte datum designed specifically to hold character data
    (UNICODE code points, in particular). It is illegal to put
    anything else into a `char`. Its representation is known to be
    some primitive integer compatible with `u32`, so it is cheap to
    copy, pass as an argument to a function, put in a `struct` and
    so on, but conversion to and from other types is explicit.

    I wouldn't have expected anyone to do that on a PDP-11/20 in
    1972, though.

    - Dan C.

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

    cross@spitfire.i.gajendra.net (Dan Cross) writes:
    In article <1153hcv$ba35$1@kst.eternal-september.org>,
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
    cross@spitfire.i.gajendra.net (Dan Cross) writes:
    [...]
    Cast the value when using as the index:

    while (*s) ++counts[(unsignd char)*s++];

    Note that this is already required for the `is*` functions
    defined in `ctype.h` (except, IIRC, `isascii`).

    isascii() is not defined by ISO C, or even by POSIX.

    Ah, right you are. `isascii` was marked obsolescent in POSIX
    Issue 7 (2018) and removed in Issue 8 (2024); it never made it
    into standardized C, and was dropped during the initial work
    leading up to ANSI C (the C89 rationale discusses it), though it
    remains broadly implemented, presumably for compatibility with
    older code.

    isblank() is
    another common extension. For implementations that support them,
    I don't think they're handled differently from the other is*()
    functions. Most implementations handle values from SCHAR_MIN to
    UCHAR_MAX without error, but the behavior is undefined for any
    value other than EOF outside the range 0..UCHAR_MAX.

    Before removal from POSIX, `isascii` was specified as defined
    for all integer values. https://pubs.opengroup.org/onlinepubs/9699919799/functions/isascii.html

    I imagine that `isblank` would be implemented similarly to the
    others, however.

    Interesting. The 2018 POSIX specification says that "The isascii()
    function is defined on all integer values.", but for isblank() and
    isdigit() it says "The c argument is an int, the value of which the
    application shall ensure is a character representable as an unsigned
    char or equal to the value of the macro EOF. If the argument has any
    other value, the behavior is undefined.". (I presume the same applies
    to the other ISO-C-defined functions, but I haven't checked them all.)

    isascii() is (was?) a special case, probably because it's easier to
    implement without using a lookup table. In glibc:

    #define __isascii(c) (((c) & ~0x7f) == 0)
    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@cross@spitfire.i.gajendra.net (Dan Cross) to comp.lang.c on Fri Aug 7 18:32:17 2026
    From Newsgroup: comp.lang.c

    In article <115550j$rpsl$1@kst.eternal-september.org>,
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote: >cross@spitfire.i.gajendra.net (Dan Cross) writes:
    In article <1153hcv$ba35$1@kst.eternal-september.org>,
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote: >>>cross@spitfire.i.gajendra.net (Dan Cross) writes:
    [...]
    Cast the value when using as the index:

    while (*s) ++counts[(unsignd char)*s++];

    Note that this is already required for the `is*` functions
    defined in `ctype.h` (except, IIRC, `isascii`).

    isascii() is not defined by ISO C, or even by POSIX.

    Ah, right you are. `isascii` was marked obsolescent in POSIX
    Issue 7 (2018) and removed in Issue 8 (2024); it never made it
    into standardized C, and was dropped during the initial work
    leading up to ANSI C (the C89 rationale discusses it), though it
    remains broadly implemented, presumably for compatibility with
    older code.

    isblank() is
    another common extension. For implementations that support them,
    I don't think they're handled differently from the other is*()
    functions. Most implementations handle values from SCHAR_MIN to >>>UCHAR_MAX without error, but the behavior is undefined for any
    value other than EOF outside the range 0..UCHAR_MAX.

    Before removal from POSIX, `isascii` was specified as defined
    for all integer values.
    https://pubs.opengroup.org/onlinepubs/9699919799/functions/isascii.html

    I imagine that `isblank` would be implemented similarly to the
    others, however.

    Interesting. The 2018 POSIX specification says that "The isascii()
    function is defined on all integer values.", but for isblank() and
    isdigit() it says "The c argument is an int, the value of which the >application shall ensure is a character representable as an unsigned
    char or equal to the value of the macro EOF. If the argument has any
    other value, the behavior is undefined.". (I presume the same applies
    to the other ISO-C-defined functions, but I haven't checked them all.)

    I think that's right. I have a vague memory of lore that said
    one should write, `if (isascii(c) && iswhatever(c))` (or the
    equivalent for logically negative tests), though I can no longer
    remember _where_ I saw that. Of course, once localization is in
    play, let alone portability to EBCDIC or whatever, it's less
    relevant if not outright wrong.

    isascii() is (was?) a special case, probably because it's easier to
    implement without using a lookup table. In glibc:

    #define __isascii(c) (((c) & ~0x7f) == 0)

    Yes, `isascii` is easy. Not so much for other locales, let
    alone for Unicode generally or UTF-8. As ASCII specifically has
    slid from relevance, and localization led to widespread
    adoption of UTF-8 and other encodings, one can see how it was
    merely an anachronism to be removed.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.c on Fri Aug 7 20:51:08 2026
    From Newsgroup: comp.lang.c

    On 2026-08-07 13:02, Dan Cross wrote:
    In article <1153hcv$ba35$1@kst.eternal-september.org>,
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
    cross@spitfire.i.gajendra.net (Dan Cross) writes:
    [...]
    Cast the value when using as the index:

    while (*s) ++counts[(unsignd char)*s++];

    Note that this is already required for the `is*` functions
    defined in `ctype.h` (except, IIRC, `isascii`).

    isascii() is not defined by ISO C, or even by POSIX.

    Ah, right you are. `isascii` was marked obsolescent in POSIX
    Issue 7 (2018) and removed in Issue 8 (2024); it never made it
    into standardized C, and was dropped during the initial work
    leading up to ANSI C (the C89 rationale discusses it), though it
    remains broadly implemented, presumably for compatibility with
    older code.

    (A side track about 'isascii'...)

    I seem to have a faint recollection that isascii() once had been a
    _necessary_ predicate to make the other ctype.h functions provide
    a *valid* response [in non-ASCII contexts]. (I thought that I might
    have got that from K&R, but no, there's no mention of isascii() at
    all in my copy.) - Though a quick search lead me to a man page that
    says (e.g. for 'isalpha') about 'isascii':

    "isalpha is a macro which classifies ASCII integer values by table
    lookup. It is a predicate returning non-zero when c represents an
    alphabetic ASCII character, and 0 otherwise. It is defined only
    when isascii(c) is true or c is EOF."

    (Memory seems to work.)

    With I18N and localization obviously just a legacy topic meanwhile.

    Janis

    [...]

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.c on Fri Aug 7 20:55:09 2026
    From Newsgroup: comp.lang.c

    On 2026-08-07 20:32, Dan Cross wrote:
    [...]

    I think that's right. I have a vague memory of lore that said
    one should write, `if (isascii(c) && iswhatever(c))` (or the
    equivalent for logically negative tests), though I can no longer
    remember _where_ I saw that. Of course, once localization is in
    play, let alone portability to EBCDIC or whatever, it's less
    relevant if not outright wrong.

    Same memories here. - And you're not wrong. (See my other reply
    just a few minutes ago.)

    Janis

    [..]

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@Keith.S.Thompson+u@gmail.com to comp.lang.c on Fri Aug 7 13:03:12 2026
    From Newsgroup: comp.lang.c

    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
    On 2026-08-07 13:02, Dan Cross wrote:
    In article <1153hcv$ba35$1@kst.eternal-september.org>,
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
    cross@spitfire.i.gajendra.net (Dan Cross) writes:
    [...]
    Cast the value when using as the index:

    while (*s) ++counts[(unsignd char)*s++];

    Note that this is already required for the `is*` functions
    defined in `ctype.h` (except, IIRC, `isascii`).

    isascii() is not defined by ISO C, or even by POSIX.
    Ah, right you are. `isascii` was marked obsolescent in POSIX
    Issue 7 (2018) and removed in Issue 8 (2024); it never made it
    into standardized C, and was dropped during the initial work
    leading up to ANSI C (the C89 rationale discusses it), though it
    remains broadly implemented, presumably for compatibility with
    older code.

    (A side track about 'isascii'...)

    I seem to have a faint recollection that isascii() once had been a _necessary_ predicate to make the other ctype.h functions provide
    a *valid* response [in non-ASCII contexts]. (I thought that I might
    have got that from K&R, but no, there's no mention of isascii() at
    all in my copy.) - Though a quick search lead me to a man page that
    says (e.g. for 'isalpha') about 'isascii':

    "isalpha is a macro which classifies ASCII integer values by table
    lookup. It is a predicate returning non-zero when c represents an
    alphabetic ASCII character, and 0 otherwise. It is defined only
    when isascii(c) is true or c is EOF."

    (Memory seems to work.)

    With I18N and localization obviously just a legacy topic meanwhile.

    That must be an old man page. Where did you find it?

    isascii() (on systems where it's provided) is true for arguments in the
    range 0..127, false for anything else. The above implies that isalpha()
    has undefined behavior for values above 127, which contradicts the ISO C requirement that it's defined for values in the range of unsigned char
    (0..255 in almost all implementations).

    newlib, the C library implementation used by Cygwin, has similar wording
    in its isspace(3) man page:

    isspace is a macro which classifies singlebyte charset values by
    table lookup. It is a predicate returning non-zero for whitespace
    characters, and 0 for other characters. It is defined only when
    isascii(c) is true or c is EOF.

    In fact isspace() is implemented correctly, returning non-zero
    (happens to be 1) for '\t', '\n', '\v', '\f', '\r', and ' ', and
    zero for all other values in the range 128..255 and for -1 (EOF).

    Apparently the man page hasn't been updated in a long time.
    The is*() functions have been defined for EOF and all values from
    0 to UCHAR_MAX since C89/C90.
    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@Keith.S.Thompson+u@gmail.com to comp.lang.c on Fri Aug 7 13:32:29 2026
    From Newsgroup: comp.lang.c

    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    [...]
    newlib, the C library implementation used by Cygwin, has similar wording
    in its isspace(3) man page:

    isspace is a macro which classifies singlebyte charset values by
    table lookup. It is a predicate returning non-zero for whitespace
    characters, and 0 for other characters. It is defined only when
    isascii(c) is true or c is EOF.

    In fact isspace() is implemented correctly, returning non-zero
    (happens to be 1) for '\t', '\n', '\v', '\f', '\r', and ' ', and
    zero for all other values in the range 128..255 and for -1 (EOF).

    Apparently the man page hasn't been updated in a long time.
    The is*() functions have been defined for EOF and all values from
    0 to UCHAR_MAX since C89/C90.

    This only affects the isspace(3) man page; the other is*(3) man pages
    are correct.

    I've reported this to the Cygwin mailing list.

    https://cygwin.com/pipermail/cygwin/2026-August/259928.html
    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@cross@spitfire.i.gajendra.net (Dan Cross) to comp.lang.c on Fri Aug 7 21:44:11 2026
    From Newsgroup: comp.lang.c

    In article <1155dm4$uui4$1@kst.eternal-september.org>,
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
    [snip]
    I seem to have a faint recollection that isascii() once had been a
    _necessary_ predicate to make the other ctype.h functions provide
    a *valid* response [in non-ASCII contexts]. (I thought that I might
    have got that from K&R, but no, there's no mention of isascii() at
    all in my copy.) - Though a quick search lead me to a man page that
    says (e.g. for 'isalpha') about 'isascii':

    "isalpha is a macro which classifies ASCII integer values by table
    lookup. It is a predicate returning non-zero when c represents an
    alphabetic ASCII character, and 0 otherwise. It is defined only
    when isascii(c) is true or c is EOF."

    (Memory seems to work.)

    With I18N and localization obviously just a legacy topic meanwhile.

    That must be an old man page. Where did you find it?

    I just looked around my menagerie of old Unix versions, and that
    language (or similar) was common util through at least
    4.3BSD-Tahoe, and retained all the way through 10th Edition
    Research Unix (which was actually based on ~4.1BSD).

    isascii() (on systems where it's provided) is true for arguments in the
    range 0..127, false for anything else. The above implies that isalpha()
    has undefined behavior for values above 127, which contradicts the ISO C >requirement that it's defined for values in the range of unsigned char >(0..255 in almost all implementations).

    I think if it is on a system that says one has to use `isascii`
    prior to one of the other predicates defined in `<ctype.h>`, it
    is safe to assume it predates standard C.

    newlib, the C library implementation used by Cygwin, has similar wording
    in its isspace(3) man page:

    isspace is a macro which classifies singlebyte charset values by
    table lookup. It is a predicate returning non-zero for whitespace
    characters, and 0 for other characters. It is defined only when
    isascii(c) is true or c is EOF.

    In fact isspace() is implemented correctly, returning non-zero
    (happens to be 1) for '\t', '\n', '\v', '\f', '\r', and ' ', and
    zero for all other values in the range 128..255 and for -1 (EOF).

    Apparently the man page hasn't been updated in a long time.
    The is*() functions have been defined for EOF and all values from
    0 to UCHAR_MAX since C89/C90.

    I am disappointed, but unsurprised. The art of writing man
    pages (and troff, for that matter) is quickly becoming a lost
    art.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.c on Fri Aug 7 23:47:14 2026
    From Newsgroup: comp.lang.c

    On 2026-08-07 22:03, Keith Thompson wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
    On 2026-08-07 13:02, Dan Cross wrote:
    In article <1153hcv$ba35$1@kst.eternal-september.org>,
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
    cross@spitfire.i.gajendra.net (Dan Cross) writes:
    [...]
    Cast the value when using as the index:

    while (*s) ++counts[(unsignd char)*s++];

    Note that this is already required for the `is*` functions
    defined in `ctype.h` (except, IIRC, `isascii`).

    isascii() is not defined by ISO C, or even by POSIX.
    Ah, right you are. `isascii` was marked obsolescent in POSIX
    Issue 7 (2018) and removed in Issue 8 (2024); it never made it
    into standardized C, and was dropped during the initial work
    leading up to ANSI C (the C89 rationale discusses it), though it
    remains broadly implemented, presumably for compatibility with
    older code.

    (A side track about 'isascii'...)

    I seem to have a faint recollection that isascii() once had been a
    _necessary_ predicate to make the other ctype.h functions provide
    a *valid* response [in non-ASCII contexts]. (I thought that I might
    have got that from K&R, but no, there's no mention of isascii() at
    all in my copy.) - Though a quick search lead me to a man page that
    says (e.g. for 'isalpha') about 'isascii':

    "isalpha is a macro which classifies ASCII integer values by table
    lookup. It is a predicate returning non-zero when c represents an
    alphabetic ASCII character, and 0 otherwise. It is defined only
    when isascii(c) is true or c is EOF."

    (Memory seems to work.)

    With I18N and localization obviously just a legacy topic meanwhile.

    That must be an old man page.

    Yes, likely. - As I've said, that was a legacy thing that I (and as it
    seems also Dan) remembered. - If I'd have to date that information I'd
    guess it must have been somewhere around 1985-95 that I've read it in
    some Unix man page on some of the platforms I used back then.[*]

    (The quote just backs up our memories as not being pure imaginations.)

    Where did you find it?

    It was the first hit of a Web search. I haven't stored it because it's
    nowadays meaningless.[**]

    Janis

    [*] If someone wants to look up man pages on those platforms, it may be
    one of UTS (Amdahl), SunOS 4 (Sun), AIX 3.x (IBM), HP-UX 9 (HP). But it
    (the information) may also stem from another source, but less likely.

    [**] Wait! I have it still in the cache... - but note that this library
    was *not* what _we_ used back these days.

    GNUPro C Library Copyright -- 1992-1997 Cygnus Support. https://users.informatik.haw-hamburg.de/~krabat/FH-Labor/gnupro/4_GNUPro_Libraries/a_GNUPro_C_Library/libc.html

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

    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
    On 2026-08-07 22:03, Keith Thompson wrote:
    [...]
    That must be an old man page.

    Yes, likely. - As I've said, that was a legacy thing that I (and as it
    seems also Dan) remembered. - If I'd have to date that information I'd
    guess it must have been somewhere around 1985-95 that I've read it in
    some Unix man page on some of the platforms I used back then.[*]

    (The quote just backs up our memories as not being pure imaginations.)

    Where did you find it?

    [SNIP]

    [**] Wait! I have it still in the cache... - but note that this library
    was *not* what _we_ used back these days.

    GNUPro C Library Copyright -- 1992-1997 Cygnus Support. https://users.informatik.haw-hamburg.de/~krabat/FH-Labor/gnupro/4_GNUPro_Libraries/a_GNUPro_C_Library/libc.html

    It seems that Cygwin/Newlib shares some common ancestry with GNUPro.

    The history of the newlib git repo shows a fix in 2013 that corrected
    this for most of the is*() functions. It looks like isspace() was
    simply overlooked.
    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From BGB@cr88192@gmail.com to comp.lang.c on Sun Aug 9 15:19:04 2026
    From Newsgroup: comp.lang.c

    On 8/6/2026 3:34 AM, David Brown wrote:
    On 05/08/2026 23:50, Lawrence DrCOOliveiro wrote:
    On Wed, 5 Aug 2026 13:33:44 -0400, James Kuyper wrote:

    On 2026-08-05 03:22, Lawrence DrCOOliveiro wrote:

    On Mon, 3 Aug 2026 18:38:03 -0500, BGB wrote:

    ... (though last I checked, MSVC still doesn't fully support C99;
    eg, still no VLAs or _Complex).

    If a language implementation still doesnrCOt fully cope with a
    version of the language spec that is from over a quarter century
    ago and about two subsequent revisions out of date, I would say
    that describes a product that is on rCLlife supportrCY ...

    "cope" is fairly vague. VLAs and complex math are both optional in
    the current version of C, so lack of support for those features is
    no barrier to being a fully conforming implementation.

    Technically, you might be correct.

    But when your competition is GCC, then letting yourself look bad means
    yourCOre not even trying any more.

    I don't think MS sees gcc as a competitor in this sense.-a I suspect that there are few programmers who want to use MSVC for C programming but
    choose gcc on Windows because of its support for _Complex or VLAs.

    I also think there are not many C programmers who use _Complex types -
    they are simply not useful in most coding.-a And programmers who do need complex numbers may well be choosing other languages anyway.-a (Of course "not many C programmers" does not mean /no/ C programmers,)


    Yeah, complex is rarely all that useful.


    If I were to rank these sorts of edge-case features from most to least
    from useful based on personal use (in BGBCC's dialect):
    __int128 //actually pretty useful sometimes
    SIMD vectors; //useful, but horribly non-standardized
    "short float" //Binary16
    "long double" //Binary128
    quaternions //Typically 4x Binary32 (*1)
    lambdas
    VLAs
    _Complex
    __variant //dynamic types


    *1: Though for storage savings, 4x Binary16 or 4x FP8(A) can make sense.
    In the most common use-case, rotations, Binary16 is sufficient.
    FP8A (modified A-Law) is a good storage option.
    While, strictly speaking, less accurate than 4 linear bytes;
    They become more accurate than bytes following renormalization (*2).

    *2: As any one component becomes larger, the other components become
    smaller, and the inaccuracy from the larger component(s) is compensated
    for by the smaller components, resulting in a higher average accuracy.
    While bytes (mapped from -1.0 to +1.0) are initially more accurate,
    their accuracy does not benefit from normalization, so using bytes
    effectively causes a more significant jitter of the position on the 4D
    unit sphere.

    Where, normalization here is defined as, say:
    q1 = q / sqrt(q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w);
    Because apparently some people define it differently.


    In contrast, Complex is relatively little used in my use-cases.
    Most signal processing tasks I do are real-valued;
    Not really doing anything like Mandelbrot fractals or working with
    Riemann surfaces or similar;
    Nor doing any quantum mechanics calculations or similar;
    ...


    At which point, practical use-cases for plain Complex kinda fall off.

    Even if, yes, a quaternion is more complex than a normal complex, but
    they have a "killer app" of sorts in that they are useful for storing
    the rotations of things.

    Nevermind the that effectively every possible 3D rotation is effectively represented twice and you need to rotation 720 degrees to get back to
    the original orientation. Sometimes this does result in weird quirks
    that need to be accounted for when interpolating rotations (such as
    detecting when points are near opposite sides of the unit sphere and
    then mirroring them to be closer together).

    Well, decided to leave out a big detour about rotations in free-space
    and "intermediate axis theorem" and similar. Not really relevant here.
    But, yeah, they still end up as one of the better options despite the
    720 degree quirk.


    Does either really need a C type?
    It is convenient, but debatable.


    Both would still be lower on the list than other 2 and 4 element vector
    types (and having a nice way to deal with rotations also only makes
    sense if one has a nice way to represent the thing being rotated).

    Though, could in theory store all the spatial coordinates in quaternions
    as well, but this goes against convention.

    Like, say, to rotate a 3D vector one could be like:
    point2 = (rot * point1) / rot;

    Where note that P*Q is not necessarily equal to Q*P, and both
    multiplying and dividing by a rotation need not result in identity
    (well, except with 1+0i+0j+0k or similar...).


    For normal 3D vectors, A*B is defined as a per-element multiply, but
    this is not true of quaternions.

    Well, or people can find other uses by them, and they also contain
    complex numbers as a subset, ...

    ...


    Lambdas:
    Uses a C++ style syntax:
    [capture] (args)->type { body }
    Representation:
    Function pointer of the corresponding type signature;
    Typically points to RWX memory;
    Has different rules based on capture type.
    [&] ... //implicit by-reference, local lifetime only
    [=] ... //implicit by-value, unbounded lifetime
    [] ... //no capture, unbounded lifetime
    Can also list captures individually if desired.

    Rarely used...
    Note that non-careful use of [=] lambdas can result in a memory leak;
    [&] lambdas don't leak as they are auto-destroyed;
    [] lambdas don't leak, as nothing is created to be leaked.

    Can note that (from a compiler POV) lambdas are a pain to deal with, as
    the compiler effectively needs to fold them into their own function
    bodies with an implicit context structure for the captures.

    This context structure is usually preceded with a stub:
    Loads itself into a register;
    Branches to the actual lambda function's entry point.

    Typically needs special RWX memory, which is not used for general heap
    or stack memory as it provides a safety risk (RWX memory for heap or
    stack leaves an attack surface for shell-code injection).


    VLAs are also not very common in C programming, and what is found is
    often arrays that are technically VLAs, but in practice are sizes that
    are known at compile time - the size is given by a variable (that is, or could be, declared "const") that is fixed.-a In C++, such "const"
    variables can be used as the size of an array - these are normal arrays
    in C++, but technically VLAs in C.-a MSVC users can get that by compiling their C code as C++, which is something I have seen MSVC users do
    without realising it.

    It would be best, of course, if MS simply added these C99 features to
    their C compiler.-a I do not think it is beyond their technical abilities
    or that it would be a huge effort.-a (It doesn't need to be particularly efficient.)


    The main argument against the traditional notion of VLAs is that it
    implies variable-sized stack-frames, but there are other options:
    Offer a small brk-like or hunk-like mechanism;
    If space remains, and the alloc is under the size limit, use this;
    Fall back heap allocations with an implicit chain-freeing mechanism.

    So, say, for the brk-like mechanism:
    A modest, likely fixed-size region exists per-thread;
    Keep track of its position when used in a frame;
    Returning from a frame will restore its prior position;
    Enforces a size limit for allocs.
    Point is mostly to make small VLAs fast;
    Defeated if it all gets used up by a big VLA.

    For the heap-based mechanism:
    Keep a linked list of allocs;
    Existing a frame also frees any allocs in this list;
    Implicitly can also cover automatic objects and lambdas.

    In this strategy, each stack frame can remain fixed size.


    Making VLAs and _Complex optional in C11 was, I think, a mistake.-a It is fair enough to make /new/ features optional in a new standard - and then perhaps make them required features in later standards if they are
    popular enough.-a I don't know if MS was instrumental in changing VLAs
    and _Complex to optional features in C11, but it certainly gives that impression.


    I think they were in this case.
    Or, at least, MS's refusal to implement them probably didn't exactly
    help matters...

    IMO, unlike VLAs, there is no particularly strong technical reason for
    not implementing _Complex though (they don't really require any
    infrastructure that the compiler wouldn't have likely already needed for
    other reasons).

    ...


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Sun Aug 9 20:33:33 2026
    From Newsgroup: comp.lang.c

    On Sun, 9 Aug 2026 15:19:04 -0500, BGB wrote:

    In contrast, Complex is relatively little used in my use-cases. Most
    signal processing tasks I do are real-valued;

    The Complex data type lets you represent amplitude and phase both in
    one number. DonrCOt you have to deal with phases in your signals?
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c on Sun Aug 9 18:03:47 2026
    From Newsgroup: comp.lang.c

    On 8/9/2026 1:19 PM, BGB wrote:
    [...]
    Yeah, complex is rarely all that useful.
    [...]

    For me personally, its very useful. But, well, that's just me.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c on Sun Aug 9 18:04:47 2026
    From Newsgroup: comp.lang.c

    On 8/9/2026 1:33 PM, Lawrence DrCOOliveiro wrote:
    On Sun, 9 Aug 2026 15:19:04 -0500, BGB wrote:

    In contrast, Complex is relatively little used in my use-cases. Most
    signal processing tasks I do are real-valued;

    The Complex data type lets you represent amplitude and phase both in
    one number. DonrCOt you have to deal with phases in your signals?

    I love them. Use them, etc... Now, why doesn't C support the triplex
    numbers? Who gives a shit! ;^) But, yet, they are, sometimes, important
    to me.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Mon Aug 10 02:45:32 2026
    From Newsgroup: comp.lang.c

    On Sun, 9 Aug 2026 18:04:47 -0700, Chris M. Thomasson wrote:

    Now, why doesn't C support the triplex numbers?

    What are rCLtriplex numbersrCY? Hamilton tried to generalize complex
    numbers to three dimensions, but found you couldnrCOt do it with 3
    components, you needed 4. Hence quaternions.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@david.brown@hesbynett.no to comp.lang.c on Mon Aug 10 08:58:21 2026
    From Newsgroup: comp.lang.c

    On 10/08/2026 03:03, Chris M. Thomasson wrote:
    On 8/9/2026 1:19 PM, BGB wrote:
    [...]
    Yeah, complex is rarely all that useful.
    [...]

    For me personally, its very useful. But, well, that's just me.

    Of course. As I said, /few/ programmers does not mean /no/ programmers.
    Complex numbers are clearly useful in some types of code. So are
    other types of numbers, such as quaternions. It is rarely clear when a feature is useful enough to make it part of a language and standard
    library (thus allowing "z = x + y * i;" rather than using function call
    or macro syntax), or when it should be left to external libraries.

    But since _Complex was added to C99, as a non-optional feature, I
    believe it should have stayed non-optional.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c on Mon Aug 10 02:24:12 2026
    From Newsgroup: comp.lang.c

    On 8/9/2026 7:45 PM, Lawrence DrCOOliveiro wrote:
    On Sun, 9 Aug 2026 18:04:47 -0700, Chris M. Thomasson wrote:

    Now, why doesn't C support the triplex numbers?

    What are rCLtriplex numbersrCY? Hamilton tried to generalize complex
    numbers to three dimensions, but found you couldnrCOt do it with 3 components, you needed 4. Hence quaternions.

    https://www.soler7.com/Fractals/Matrices%20to%20Triplex.pdf

    They are useful for computing the mandelbulb.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From BGB@cr88192@gmail.com to comp.lang.c on Mon Aug 10 15:17:45 2026
    From Newsgroup: comp.lang.c

    On 8/10/2026 1:58 AM, David Brown wrote:
    On 10/08/2026 03:03, Chris M. Thomasson wrote:
    On 8/9/2026 1:19 PM, BGB wrote:
    [...]
    Yeah, complex is rarely all that useful.
    [...]

    For me personally, its very useful. But, well, that's just me.

    Of course.-a As I said, /few/ programmers does not mean /no/ programmers.
    -aComplex numbers are clearly useful in some types of code.-a So are
    other types of numbers, such as quaternions.-a It is rarely clear when a feature is useful enough to make it part of a language and standard
    library (thus allowing "z = x + y * i;" rather than using function call
    or macro syntax), or when it should be left to external libraries.

    But since _Complex was added to C99, as a non-optional feature, I
    believe it should have stayed non-optional.


    Generally agree...

    Usual reason to add features to the language proper is when they are either: Highly used, so it is about programmer convenience;
    Can be made a lot more computationally efficient by having them
    in-language rather than as a library feature (most SIMD/vector stuff
    fits here).



    Also interesting in a way that other people think quaternions can be
    useful, as (in general) they seem to be rather rarely used (and rarely
    known to most people).


    They are helped by having a combined shuffle-and-trisate-multiply operator.

    This can potentially reduce things down to around 6 instructions for a
    cross product or 8 for a quaternion product (if one were using SIMD FMAC).

    If one could have a combined "shuffles and vector FMA" instruction, this
    could do the cross and quat product in 3 or 4 instructions. Couldn't
    really do this before because it asks too much for timing and similar.


    Well, and currently the fastest sequence would actually use 11
    instructions for a quaternion product (and would need around 13 clock
    cycles for Binary32).

    Did (very) recently slightly optimize this by also adding it for the
    32-bit shuffle (vs just the 16-bit shuffle).


    This being because in this case separate SIMD multiply-and-add would outperform trying to use fused-multiply-add. This might be true even if
    not for the steep penalty of the current SIMD FMA ops; even if the ops themselves were same speed and latency of the PMUL ops, the minimal case
    would still end up slower register due to RAW dependencies between the
    FMA ops (would need to wait the full latency rather than being able to pipeline stuff).


    A vector/matrix multiply is a similar number of instructions, but would
    need more cycles in total due mostly to memory load latency (memory
    loads cost more than shuffles).

    Well, except vector/matrix multiply is typically one and done.
    R*Pt/R
    Still leaves the /R part, which effectively involves a FP division step.

    Say:
    R^-1 = (R.r-R.i-R.j-R.k) / (R.r*R.r + R.i*R.i + R.j*R.j + R.k*R.k)
    The conjugate and dot product are cheap here, the FDIV, not so much...
    Well, unless accuracy doesn't matter and one can cheese the FDIV.

    ...

    Yeah...

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@Keith.S.Thompson+u@gmail.com to comp.lang.c on Mon Aug 10 15:19:48 2026
    From Newsgroup: comp.lang.c

    BGB <cr88192@gmail.com> writes:
    On 8/10/2026 1:58 AM, David Brown wrote:
    On 10/08/2026 03:03, Chris M. Thomasson wrote:
    On 8/9/2026 1:19 PM, BGB wrote:
    [...]
    Yeah, complex is rarely all that useful.
    [...]

    For me personally, its very useful. But, well, that's just me.
    Of course.-a As I said, /few/ programmers does not mean /no/
    programmers. -aComplex numbers are clearly useful in some types of
    code.-a So are other types of numbers, such as quaternions.-a It is
    rarely clear when a feature is useful enough to make it part of a
    language and standard library (thus allowing "z = x + y * i;" rather
    than using function call or macro syntax), or when it should be left
    to external libraries.

    But since _Complex was added to C99, as a non-optional feature, I
    believe it should have stayed non-optional.

    Generally agree...

    Usual reason to add features to the language proper is when they are either: Highly used, so it is about programmer convenience;
    Can be made a lot more computationally efficient by having them
    in-language rather than as a library feature (most SIMD/vector stuff
    fits here).
    [...]

    In this case, there's another reason: notational convenience.

    Since C doesn't have operator overloading, adding complex numbers
    as a library feature would have required function call notation for
    all operators, and since there are complex types corresponding to
    all three floating-point types, that would have led to an explosion
    of function names. By making complex types a new core feature of
    the language, it was possible to use "+" for addition.

    C++ complex numbers are implemented as a library class with
    overloaded operators.

    (I agree that making them optional was a bad idea -- at least for hosted implementations.)
    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From BGB@cr88192@gmail.com to comp.lang.c on Mon Aug 10 17:31:14 2026
    From Newsgroup: comp.lang.c

    On 8/10/2026 5:19 PM, Keith Thompson wrote:
    BGB <cr88192@gmail.com> writes:
    On 8/10/2026 1:58 AM, David Brown wrote:
    On 10/08/2026 03:03, Chris M. Thomasson wrote:
    On 8/9/2026 1:19 PM, BGB wrote:
    [...]
    Yeah, complex is rarely all that useful.
    [...]

    For me personally, its very useful. But, well, that's just me.
    Of course.-a As I said, /few/ programmers does not mean /no/
    programmers. -aComplex numbers are clearly useful in some types of
    code.-a So are other types of numbers, such as quaternions.-a It is
    rarely clear when a feature is useful enough to make it part of a
    language and standard library (thus allowing "z = x + y * i;" rather
    than using function call or macro syntax), or when it should be left
    to external libraries.

    But since _Complex was added to C99, as a non-optional feature, I
    believe it should have stayed non-optional.

    Generally agree...

    Usual reason to add features to the language proper is when they are either: >> Highly used, so it is about programmer convenience;
    Can be made a lot more computationally efficient by having them
    in-language rather than as a library feature (most SIMD/vector stuff
    fits here).
    [...]


    Snipped section included my epic fail at trying to use traditional style mathematical notation in a Usenet post...

    It was bugging me, by implying the conjugate was a scalar, where no, the conjugate is not a scalar...


    In this case, there's another reason: notational convenience.

    Since C doesn't have operator overloading, adding complex numbers
    as a library feature would have required function call notation for
    all operators, and since there are complex types corresponding to
    all three floating-point types, that would have led to an explosion
    of function names. By making complex types a new core feature of
    the language, it was possible to use "+" for addition.


    Yes, likewise.

    In my case, I extended operator notation to _Complex, __quatf and
    similar, and also to things like __vec4.


    C++ complex numbers are implemented as a library class with
    overloaded operators.


    Though the drawback here is that then it leaves more heavy lifting for
    the compiler if you want them to also be fast(ish).


    (I agree that making them optional was a bad idea -- at least for hosted implementations.)


    Yes.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Mon Aug 10 23:48:37 2026
    From Newsgroup: comp.lang.c

    On Mon, 10 Aug 2026 17:31:14 -0500, BGB wrote:

    Snipped section included my epic fail at trying to use traditional
    style mathematical notation in a Usenet post...

    Suggestion: why not use Latex/Mathjax notation for that? Indicated by bracketing the sequence in rCL$rCY signs, e.g.

    The thin-lens equation is ${1 \over s_o} + {1 \over s_f} = {1 \over f}$

    If you have a scratch Jupyter notebook always to hand (as I do), itrCOs
    easy enough to copy and paste that bit into a markdown cell, hit
    shift-enter, and view the result in all its typeset glory.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From James Kuyper@jameskuyper@alumni.caltech.edu to comp.lang.c on Mon Aug 10 20:03:51 2026
    From Newsgroup: comp.lang.c

    On 2026-08-10 18:31, BGB wrote:
    Snipped section included my epic fail at trying to use traditional
    style
    mathematical notation in a Usenet post...

    It was bugging me, by implying the conjugate was a scalar, where no, the conjugate is not a scalar...

    I'm not sure what you're saying. As far as C is concerned. complex types
    are floating types (6.2.5p15), and therefore arithmetic types
    (6.2.5p23), and therefore scalar types (6.2.5p26) Therefore, a function
    that returns the conjugate of its argument would return a scalar type.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From steve g@Sgonedes1977@gmail.com to comp.lang.c on Mon Aug 10 20:29:56 2026
    From Newsgroup: comp.lang.c

    BGB <cr88192@gmail.com> writes:


    [...]

    Generally agree...

    Usual reason to add features to the language proper is when they are either: Highly used, so it is about programmer convenience;
    Can be made a lot more computationally efficient by having them in-language rather than as a library feature (most SIMD/vector stuff fits here).


    I am an goofy wanna be economist...

    The reason to add "new features" is for marketing.

    The purpose of standardization is to diversify the market.

    It is like a light bulb. If the new LEDs did not fit into the "standard"
    light socket you may need to rebuild your house for better lighting.
    This will surely not succeed in the market place.

    How do I know LEDs are better than the tungsten? It is because people
    like them better. Think about those T4 lamps - not seeing them around so
    much anymore.

    I am sorry to you C people; if C was a failure would they have created
    C++ ? No! People like C, they know C; c++ just allows programmers to
    write their software in a more marketable way (this is not an offensive statement).

    I do not mean any offense to C programmers. I love the language; if C
    did not work why are people not using D?

    Have fun
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From BGB@cr88192@gmail.com to comp.lang.c on Mon Aug 10 20:44:43 2026
    From Newsgroup: comp.lang.c

    On 8/10/2026 7:03 PM, James Kuyper wrote:
    On 2026-08-10 18:31, BGB wrote:
    Snipped section included my epic fail at trying to use traditional
    style
    mathematical notation in a Usenet post...

    It was bugging me, by implying the conjugate was a scalar, where no, the
    conjugate is not a scalar...

    I'm not sure what you're saying. As far as C is concerned. complex types
    are floating types (6.2.5p15), and therefore arithmetic types
    (6.2.5p23), and therefore scalar types (6.2.5p26) Therefore, a function
    that returns the conjugate of its argument would return a scalar type.

    I wrote:
    R^-1 = (R.r-R.i-R.j-R.k) / (R.r*R.r + R.i*R.i + R.j*R.j + R.k*R.k)

    The problem:
    (R.r-R.i-R.j-R.k)
    Should have been, say:
    (R.r - R.i*I - R.j*J - R.k*K)

    Which was bugging me, because either the former would be interpreted as meaning a scalar (or real-valued) result, or "R.i*R.i" as being
    negative, neither of which was true in the intended expression...


    Seemingly no one called me out on it though...



    Well, since:
    I*I = J*J = K*K = -1
    I*J = K, J*K = I, K*I = J
    J*I = -K, K*J = -I, I*K = -J
    ...

    So, say P*Q:
    ( P.r*Q.r - P.i*Q.i - P.j*Q.j - P.k*Q.k ) +
    ( P.r*Q.i + P.i*Q.r + P.j*Q.k - P.k*Q.j )*I +
    ( P.r*Q.j - P.i*Q.k + P.j*Q.r + P.k*Q.i )*J +
    ( P.r*Q.k + P.i*Q.j - P.j*Q.i + P.k*Q.r )*K

    One challenge being to do this in as few CPU instructions as possible.
    This being a place where combining shuffle and ternary multiply into a
    single CPU instruction can help.

    Better still if one can do shuffles and negation on both vectors at the
    same time while also multiplying-and-adding the results, but this is
    where things get bad. This is where a minimal case of 4 instructions
    comes from (effectively, each column of the above multiply becoming a
    single SIMD instruction...).


    But, yeah:
    If one assumes J and K are 0, it becomes semantically equivalent to a
    complex number.

    Say:
    ( P.r*Q.r - P.i*Q.i - 0*0 - 0*0 ) +
    ( P.r*Q.i + P.i*Q.r + 0*0 - 0*0 )*I +
    ( P.r* 0 - P.i* 0 + 0*Q.r + 0*Q.i )*J +
    ( P.r* 0 + P.i* 0 - 0*Q.i + 0*Q.r )*K

    ( P.r*Q.r - P.i*Q.i ) +
    ( P.r*Q.i + P.i*Q.r )*I


    Well, and conversely, if R is 0 (and ignored), it essentially decays
    into a cross product:
    ( 0*0 - P.i*Q.i - P.j*Q.j - P.k*Q.k ) +
    ( 0*Q.i + P.i*0 + P.j*Q.k - P.k*Q.j )*I +
    ( 0*Q.j - P.i*Q.k + P.j*0 + P.k*Q.i )*J +
    ( 0*Q.k + P.i*Q.j - P.j*Q.i + P.k*0 )*K

    ( P.j*Q.k - P.k*Q.j )*I +
    ( P.k*Q.i - P.i*Q.k )*J +
    ( P.i*Q.j - P.j*Q.i )*K


    But, yeah, they are sort of a nifty tool in this way for 3D geometry and
    3D animation math similar (but traditionally much less popular than
    using 4x4 transformation matrices or similar).

    ...


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Tue Aug 11 03:58:51 2026
    From Newsgroup: comp.lang.c

    On Mon, 10 Aug 2026 15:17:45 -0500, BGB wrote:

    Also interesting in a way that other people think quaternions can be
    useful, as (in general) they seem to be rather rarely used (and
    rarely known to most people).

    Fun fact: quaternions came before vector algebra, and led to the
    development of the latter. But not before a bunch of mathematicians
    fought a rear-guard action to keep the rCLvectorrCY and rCLscalarrCY parts of
    a quaternion together, while the vector folks found that it made a lot
    of things easier if you separated them.

    If yourCOre interested, the rCLKathy Loves Physics & HistoryrCY channel recounts the story at <https://www.youtube.com/watch?v=M12CJIuX8D4>.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Ross Finlayson@ross.a.finlayson@gmail.com to comp.lang.c on Mon Aug 10 21:15:40 2026
    From Newsgroup: comp.lang.c

    On 08/09/2026 01:19 PM, BGB wrote:
    On 8/6/2026 3:34 AM, David Brown wrote:
    On 05/08/2026 23:50, Lawrence DrCOOliveiro wrote:
    On Wed, 5 Aug 2026 13:33:44 -0400, James Kuyper wrote:

    On 2026-08-05 03:22, Lawrence DrCOOliveiro wrote:

    On Mon, 3 Aug 2026 18:38:03 -0500, BGB wrote:

    ... (though last I checked, MSVC still doesn't fully support C99;
    eg, still no VLAs or _Complex).

    If a language implementation still doesnrCOt fully cope with a
    version of the language spec that is from over a quarter century
    ago and about two subsequent revisions out of date, I would say
    that describes a product that is on rCLlife supportrCY ...

    "cope" is fairly vague. VLAs and complex math are both optional in
    the current version of C, so lack of support for those features is
    no barrier to being a fully conforming implementation.

    Technically, you might be correct.

    But when your competition is GCC, then letting yourself look bad means
    yourCOre not even trying any more.

    I don't think MS sees gcc as a competitor in this sense. I suspect
    that there are few programmers who want to use MSVC for C programming
    but choose gcc on Windows because of its support for _Complex or VLAs.

    I also think there are not many C programmers who use _Complex types -
    they are simply not useful in most coding. And programmers who do
    need complex numbers may well be choosing other languages anyway. (Of
    course "not many C programmers" does not mean /no/ C programmers,)


    Yeah, complex is rarely all that useful.


    If I were to rank these sorts of edge-case features from most to least
    from useful based on personal use (in BGBCC's dialect):
    __int128 //actually pretty useful sometimes
    SIMD vectors; //useful, but horribly non-standardized
    "short float" //Binary16
    "long double" //Binary128
    quaternions //Typically 4x Binary32 (*1)
    lambdas
    VLAs
    _Complex
    __variant //dynamic types


    *1: Though for storage savings, 4x Binary16 or 4x FP8(A) can make sense.
    In the most common use-case, rotations, Binary16 is sufficient.
    FP8A (modified A-Law) is a good storage option.
    While, strictly speaking, less accurate than 4 linear bytes;
    They become more accurate than bytes following renormalization (*2).

    *2: As any one component becomes larger, the other components become
    smaller, and the inaccuracy from the larger component(s) is compensated
    for by the smaller components, resulting in a higher average accuracy.
    While bytes (mapped from -1.0 to +1.0) are initially more accurate,
    their accuracy does not benefit from normalization, so using bytes effectively causes a more significant jitter of the position on the 4D
    unit sphere.

    Where, normalization here is defined as, say:
    q1 = q / sqrt(q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w);
    Because apparently some people define it differently.


    In contrast, Complex is relatively little used in my use-cases.
    Most signal processing tasks I do are real-valued;
    Not really doing anything like Mandelbrot fractals or working with
    Riemann surfaces or similar;
    Nor doing any quantum mechanics calculations or similar;
    ...


    At which point, practical use-cases for plain Complex kinda fall off.

    Even if, yes, a quaternion is more complex than a normal complex, but
    they have a "killer app" of sorts in that they are useful for storing
    the rotations of things.

    Nevermind the that effectively every possible 3D rotation is effectively represented twice and you need to rotation 720 degrees to get back to
    the original orientation. Sometimes this does result in weird quirks
    that need to be accounted for when interpolating rotations (such as
    detecting when points are near opposite sides of the unit sphere and
    then mirroring them to be closer together).

    Well, decided to leave out a big detour about rotations in free-space
    and "intermediate axis theorem" and similar. Not really relevant here.
    But, yeah, they still end up as one of the better options despite the
    720 degree quirk.


    Does either really need a C type?
    It is convenient, but debatable.


    Both would still be lower on the list than other 2 and 4 element vector
    types (and having a nice way to deal with rotations also only makes
    sense if one has a nice way to represent the thing being rotated).

    Though, could in theory store all the spatial coordinates in quaternions
    as well, but this goes against convention.

    Like, say, to rotate a 3D vector one could be like:
    point2 = (rot * point1) / rot;

    Where note that P*Q is not necessarily equal to Q*P, and both
    multiplying and dividing by a rotation need not result in identity
    (well, except with 1+0i+0j+0k or similar...).


    For normal 3D vectors, A*B is defined as a per-element multiply, but
    this is not true of quaternions.

    Well, or people can find other uses by them, and they also contain
    complex numbers as a subset, ...

    ...


    Lambdas:
    Uses a C++ style syntax:
    [capture] (args)->type { body }
    Representation:
    Function pointer of the corresponding type signature;
    Typically points to RWX memory;
    Has different rules based on capture type.
    [&] ... //implicit by-reference, local lifetime only
    [=] ... //implicit by-value, unbounded lifetime
    [] ... //no capture, unbounded lifetime
    Can also list captures individually if desired.

    Rarely used...
    Note that non-careful use of [=] lambdas can result in a memory leak;
    [&] lambdas don't leak as they are auto-destroyed;
    [] lambdas don't leak, as nothing is created to be leaked.

    Can note that (from a compiler POV) lambdas are a pain to deal with, as
    the compiler effectively needs to fold them into their own function
    bodies with an implicit context structure for the captures.

    This context structure is usually preceded with a stub:
    Loads itself into a register;
    Branches to the actual lambda function's entry point.

    Typically needs special RWX memory, which is not used for general heap
    or stack memory as it provides a safety risk (RWX memory for heap or
    stack leaves an attack surface for shell-code injection).


    VLAs are also not very common in C programming, and what is found is
    often arrays that are technically VLAs, but in practice are sizes that
    are known at compile time - the size is given by a variable (that is,
    or could be, declared "const") that is fixed. In C++, such "const"
    variables can be used as the size of an array - these are normal
    arrays in C++, but technically VLAs in C. MSVC users can get that by
    compiling their C code as C++, which is something I have seen MSVC
    users do without realising it.

    It would be best, of course, if MS simply added these C99 features to
    their C compiler. I do not think it is beyond their technical
    abilities or that it would be a huge effort. (It doesn't need to be
    particularly efficient.)


    The main argument against the traditional notion of VLAs is that it
    implies variable-sized stack-frames, but there are other options:
    Offer a small brk-like or hunk-like mechanism;
    If space remains, and the alloc is under the size limit, use this;
    Fall back heap allocations with an implicit chain-freeing mechanism.

    So, say, for the brk-like mechanism:
    A modest, likely fixed-size region exists per-thread;
    Keep track of its position when used in a frame;
    Returning from a frame will restore its prior position;
    Enforces a size limit for allocs.
    Point is mostly to make small VLAs fast;
    Defeated if it all gets used up by a big VLA.

    For the heap-based mechanism:
    Keep a linked list of allocs;
    Existing a frame also frees any allocs in this list;
    Implicitly can also cover automatic objects and lambdas.

    In this strategy, each stack frame can remain fixed size.


    Making VLAs and _Complex optional in C11 was, I think, a mistake. It
    is fair enough to make /new/ features optional in a new standard - and
    then perhaps make them required features in later standards if they
    are popular enough. I don't know if MS was instrumental in changing
    VLAs and _Complex to optional features in C11, but it certainly gives
    that impression.


    I think they were in this case.
    Or, at least, MS's refusal to implement them probably didn't exactly
    help matters...

    IMO, unlike VLAs, there is no particularly strong technical reason for
    not implementing _Complex though (they don't really require any infrastructure that the compiler wouldn't have likely already needed for other reasons).

    ...



    Thanks for writing.

    The "matroids" are a sort of higher-order matrix, and have some
    geometric character, then "generalized matrix products" and the
    corresponding "generalized matrix inverses", as well don't simply
    fit in the usual account of square or rectangular matrices and
    the like, while yet that products of tuple and scalars and vectors
    sort of make them.

    A new term I hadn't heard before a few weeks ago was "mechanical
    sympathy", the idea of designing algorithm that it reflects the
    model of computation and operation, then there's an idea of
    alike what's "mathematical sympathy", about what objects have
    what forms that mathematics reduces them. Here there's been
    being considered the "Stall-less/Branch-less/Call-less" approaches,
    or branch-less I suppose it's usually called, not that branches
    per se are bad yet that mis-predicted or un-predictable branches
    or bad, and most all interesting algorithms have un-predictable
    branches.

    Then about the mention of SIMD, here the idea is that at least
    with regards to various vector extensions on the processor,
    they can be considered as 128-bit vectors, 16-deep, about
    designing the algorithm in these blocks, then for example
    that SSE 4.2 has one block, Arm NEON has two blocks,
    AVX2 has two blocks, AVX512 has eight blocks, SVE has more
    blocks, in terms of a limited common subset of algorithms
    that work on the layout in terms of arithmetic & logic & comparison
    that when implemented in terms of these blocks within basically
    the virtually-addressed register file of banks of blocks,
    is about a programming model for SIMD that makes for byte-wise
    operations about serial algorithms, then also besides for
    usual sorts of flow-machines that make systolic Stall-less,
    Branch-less, Call-less code that doesn't stall or evict or
    exit the pipeline, in uniform sizes and with uniform operations
    across all usual modern commodity instruction sets.
    Surfacing that to the higher-level language then though
    is contrived, yet, it's just the block as a value type
    and then a limited common subset of operations on them,
    then as with regards to being agnostic endianness and so on.

    This posts is prompted from reading about "Default signedness
    of 'plain' char", which is signed, though there are compiler
    options either way, and that usually the first thing in
    dealing with "unsigned char" is to get something equivalent
    to "uint8_t", that I was tapping at some Unicode code and
    those are unsigned for arithmetic yet the SIMD CMP or compare
    instructions only work on signed bytes across the vector,
    with regards to adding 0x80 to translate the unsigned to
    signed so the relation and equivalence relation about
    l.t. and g.t. hold when the unit only does signed comparisons,
    and without needing to unpack the vector, courtesy 2's complement.


    About variants and so on or union types, and various accounts
    for example of just boxing those in structs for example to
    make them 512-bits like cache-lines or 16-bytes like 128-bit
    vector words, or for example 4096 bytes a usual page size,
    or about the 8192 bytes and jumbo packets, it seems to be
    making for "types" and storage-class and so on, and the
    conventions of values, which most people avoid with pointers.


    The variable-length array is a bit contrived, it's either on
    the stack or on the heap or in the image, it's in static
    initialization and seems to reflect the "happy or fatal"
    sort of outlook, or for "carp, croak, and die", vis-a-vis,
    "silent exit" with regards to signals and so on and other
    things I don't much think about yet are sensible for processes
    if not so much libraries.


    So, "matroids" and "generalized matrix products" and
    "generalized matrix inverse" are their own kinds of
    things, while of course floating-point arithmetic
    is what it is.




    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Tue Aug 11 04:52:25 2026
    From Newsgroup: comp.lang.c

    On Mon, 10 Aug 2026 21:15:40 -0700, Ross Finlayson wrote:

    The "matroids" are a sort of higher-order matrix, and have some
    geometric character, then "generalized matrix products" and the
    corresponding "generalized matrix inverses", as well don't simply
    fit in the usual account of square or rectangular matrices and the
    like, while yet that products of tuple and scalars and vectors sort
    of make them.

    Tensors?
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@david.brown@hesbynett.no to comp.lang.c on Tue Aug 11 08:58:08 2026
    From Newsgroup: comp.lang.c

    On 11/08/2026 00:31, BGB wrote:
    On 8/10/2026 5:19 PM, Keith Thompson wrote:
    BGB <cr88192@gmail.com> writes:

    C++ complex numbers are implemented as a library class with
    overloaded operators.


    Though the drawback here is that then it leaves more heavy lifting for
    the compiler if you want them to also be fast(ish).


    The compiler has to do the job of generating the code no matter what. A library class in C++ for complex numbers is not going to be
    significantly more demanding for the compiler than a struct of two
    doubles in C.

    Standard C++ libraries can also use compiler-specific features or
    builtins. While you can write your own C++ complex class based around a struct of two doubles, a C++ library targeting a specific compiler could happily just be a wrapper of a "_Complex double" if the compiler
    supported it as an extension. So a well-written C++ standard library
    complex type can be just as efficient as having the feature part of the language, while also being able to work even if the compiler does not
    have such extensions.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@david.brown@hesbynett.no to comp.lang.c on Tue Aug 11 09:06:11 2026
    From Newsgroup: comp.lang.c

    On 10/08/2026 22:17, BGB wrote:


    Also interesting in a way that other people think quaternions can be
    useful, as (in general) they seem to be rather rarely used (and rarely
    known to most people).

    The major use of quaternions is for 3-D graphics, and 3-D navigation
    (whether it is real navigation, control of robot arms, or something like
    a computer game). Angles and rotations can often be easier to handle
    using quaternions than Euler angles as they can keep equations neater,
    make frame changes simpler, and avoid issues of poor resolution (or
    gimble lock) at certain angles.

    They are also popular with people doing relativity calculations, quantum mechanics, and other physics work.

    But you are of course correct that they are not as well-known as complex numbers.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From BGB@cr88192@gmail.com to comp.lang.c on Tue Aug 11 04:03:19 2026
    From Newsgroup: comp.lang.c

    On 8/11/2026 1:58 AM, David Brown wrote:
    On 11/08/2026 00:31, BGB wrote:
    On 8/10/2026 5:19 PM, Keith Thompson wrote:
    BGB <cr88192@gmail.com> writes:

    C++ complex numbers are implemented as a library class with
    overloaded operators.


    Though the drawback here is that then it leaves more heavy lifting for
    the compiler if you want them to also be fast(ish).


    The compiler has to do the job of generating the code no matter what.-a A library class in C++ for complex numbers is not going to be
    significantly more demanding for the compiler than a struct of two
    doubles in C.


    A struct with two doubles is also a problem...

    Ideally, you want it as a built-in type, this way the compiler can have special logic paths for it; and to create a good place to plug in the
    SIMD instructions and SIMD related register allocation handling and similar.

    Can't really easily do this with structs and functions as this would
    also require a significant amount of heavy-lifting on the compiler's part.

    Similar reasons to why one generally needs to use things like SIMD types
    or SIMD intrinsics to really get a strong benefit from SIMD instructions (well, and then the hassle of all this stuff being poorly standardized; depending mostly on the combination of compiler and platform).


    Like, auto-vectorization exists, and often sorta works, but the
    situation is often far from ideal.


    Standard C++ libraries can also use compiler-specific features or builtins.-a While you can write your own C++ complex class based around a struct of two doubles, a C++ library targeting a specific compiler could happily just be a wrapper of a "_Complex double" if the compiler
    supported it as an extension.-a So a well-written C++ standard library complex type can be just as efficient as having the feature part of the language, while also being able to work even if the compiler does not
    have such extensions.


    Hmm...
    struct dcomplex {
    __mm128 v;
    };
    dcomplex operator+(dcomplex a, dcomplex b)
    {
    dcomplex c;
    c.v=_mm_add_pd(a.v, b.v);
    return c;
    }
    ...
    Then hope the compiler doesn't add too much overhead from all this.


    In my compiler, I went a little higher level:
    "_Complex float" "_Complex double" //native 2-element SIMD types;
    __vec2f, __vec3f, __vec4f
    __vec2d, __vec3d, __vec4d
    __vec2h, __vec3h, __vec4h, __vec2sf, __vec3sf, __vec4sf
    __quath/__quatsf, __quatf, __quatd

    No built-in matrix types or similar at present though (unlike GLSL).


    All of these exist as built-in native types.
    Note that it is possible to pull elements out of them, or sub-vectors,
    etc. But, it is not possible to assign elements.

    f=v.x; //yep, fine
    v1=v0.xy; //also fine

    v.x=f; //illegal


    Does mean there are a fair number of built-in types though.
    Much of the type-handling in BGBCC is via predicates.

    So:
    TypeCategoryP(type)
    //does type belong in a given category

    TypeSmallSometypeP(type)
    //is type along a path that promotes to Sometype

    ...

    There are a few paths that can turn into a big N*M mess though, like the
    CONV handling in the backend. This needs to deal with every possible
    type that may be cast into whatever other type for which is is possible
    to cast them.

    Well, and a subset of types that are "compatible" as-in, type conversion doesn't require any actual conversion and it if viable mostly to simply re-label the value from one type to the other. This would be types that
    are semantically unique but have the same in-register format.


    The later is partly how a lot of the __m64 and __m128 casting works, as
    these types are "compatible" with a lot of types that wouldn't otherwise
    be compatible, so they can allow a multi-step cast to effectively
    relabel a working variable reference from one type to another (and thus essentially perform a raw bit copy when the value is used).

    Though, this can create a headache on an ISA like RV64G:
    double f;
    int e;
    e=(((long long)((__m64)f))>>52)&2047;
    While it looks innocent enough, can result in an awkward situation where
    an F register shows up as an input to an integer instruction (X
    registers only on RV64G), where the ISA has separate X and F registers.
    This sort of situation ended up needing to be awkwardly hacked around
    for RV64G.

    This could be dealt with by making __m64 and similar less universally compatible of RV64G, but this would also result in an increase of no-op register moves (and diminish the relative benefit of __m64).


    Can note that a lot of compilers seem to have a smaller number of
    built-in types though...

    As is, I am sitting at around 100 built-in types.

    A lot are due to combinations of features:
    Various type sizes;
    Combination of vector lengths and base types;
    ...

    ...


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Ross Finlayson@ross.a.finlayson@gmail.com to comp.lang.c on Tue Aug 11 06:45:21 2026
    From Newsgroup: comp.lang.c

    On 08/10/2026 09:52 PM, Lawrence DrCOOliveiro wrote:
    On Mon, 10 Aug 2026 21:15:40 -0700, Ross Finlayson wrote:

    The "matroids" are a sort of higher-order matrix, and have some
    geometric character, then "generalized matrix products" and the
    corresponding "generalized matrix inverses", as well don't simply
    fit in the usual account of square or rectangular matrices and the
    like, while yet that products of tuple and scalars and vectors sort
    of make them.

    Tensors?


    The "tensors is as tensors does", about tensorial products and
    that the point of tensors is that they mean tensorial products,
    usually in a setting of vectorial products, it's a bit different
    than "it is what it is", the interleaved "logical" and "physical"
    layers, and "it is what it does", the logical layer or abstraction,
    then that tensors has that engineers have tensors which are often
    framed as systems of linear invariants, and physicists have tensors
    which are often framed as systems of linear invariants, then that
    vector spaces are often usual to everyone, yet some people just call
    their systems of "vectors" their "tensors", that matroids and tensors
    are alike in that sense, yet that matroids have a sort of "universal
    matroid" or "uniform matroid", while tensors are often described as
    systems and conventions abotu vector or linear invariants, when though
    that's as they fulfill "what it does", maintaining systemic invariants,
    that for example the linear has partials or the non-linear and the
    vectorial has, for example, "gimbal lock", or singularities, which is an example of something that the quaternion avoids, then that
    "tensors" are usually described as both the system and the elements,
    ignoring the difference, to keep things tight the tensors.

    So, "tensor" used in the field like "we have a tensor machine"
    usually enough is gussied-up "we have a system of linear invariants
    according to a vector model", since "tensor" is a bit wider itself.

    It is what it does, ....


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@cross@spitfire.i.gajendra.net (Dan Cross) to comp.lang.c on Tue Aug 11 13:46:38 2026
    From Newsgroup: comp.lang.c

    In article <115dot7$3ihmr$1@dont-email.me>,
    James Kuyper <jameskuyper@alumni.caltech.edu> wrote:
    On 2026-08-10 18:31, BGB wrote:
    Snipped section included my epic fail at trying to use traditional
    style
    mathematical notation in a Usenet post...

    It was bugging me, by implying the conjugate was a scalar, where no, the
    conjugate is not a scalar...

    I'm not sure what you're saying. As far as C is concerned.

    Was it not clear to you that he was referring to the definition
    of a complex conjugate, in the mathematical sense?

    The conjugate of a complex number is also a complex number, and
    it is common in elementary mathematics to regard such numbers as
    a vector (specifically a pair) consisting of a real component,
    and an imaginary component. Some other fields think of complex
    numbers as scalars, but I would expect the person you replied to
    to think of a complex number z=a+bi as an ordered pair, <a,b>,
    where a,b are real numbers and where "a" is the value of the
    real component, and "b" is the (real) factor of the imaginary
    component. The complex conjugate of z is then z*=a-bi=<a,-b>,
    is also a vector.

    This is totally independent of how C defines things; because C
    defines its complex type as a "scalar type" does not mean that
    in the mathematical sense, complex numbers cannot be thought of
    as vectors. Besides, math was here first.

    complex types
    are floating types (6.2.5p15), and therefore arithmetic types
    (6.2.5p23), and therefore scalar types (6.2.5p26) Therefore, a function
    that returns the conjugate of its argument would return a scalar type.

    This is exactly the danger of an overly pedantic reading: it
    leads to attempts to apply one's knowledge of some domain
    (such as C) to things outside that domain (such as mathematics).
    Being overly rigid in one's thinking and interpretations is not
    a sign of expertise, but rather, of the inability to abstract
    appropriately.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From James Kuyper@jameskuyper@alumni.caltech.edu to comp.lang.c on Tue Aug 11 11:17:42 2026
    From Newsgroup: comp.lang.c

    On 2026-08-10 21:44, BGB wrote:
    On 8/10/2026 7:03 PM, James Kuyper wrote:
    On 2026-08-10 18:31, BGB wrote:
    Snipped section included my epic fail at trying to use traditional
    style
    mathematical notation in a Usenet post...

    It was bugging me, by implying the conjugate was a scalar, where no, the >>> conjugate is not a scalar...

    I'm not sure what you're saying. As far as C is concerned. complex types
    are floating types (6.2.5p15), and therefore arithmetic types
    (6.2.5p23), and therefore scalar types (6.2.5p26) Therefore, a function
    that returns the conjugate of its argument would return a scalar type.

    I wrote:
    R^-1 = (R.r-R.i-R.j-R.k) / (R.r*R.r + R.i*R.i + R.j*R.j + R.k*R.k)

    The problem:
    (R.r-R.i-R.j-R.k)
    Should have been, say:
    (R.r - R.i*I - R.j*J - R.k*K)

    Which was bugging me, because either the former would be interpreted as meaning a scalar (or real-valued) result, or "R.i*R.i" as being
    negative, neither of which was true in the intended expression...

    I was confused because you were writing about complex numbers, mentioned
    that you had snipped some material, and then made a comment that I
    assumed, from context, was also about complex numbers. I did not realize
    that there was a context switch to quaternions inside the snipped material.
    In the unlikely event that that were added to C, quaternions would
    almost certainly be added as a new arithmetic (and therefore, scalar)
    type, by analogy with the complex types. I was unaware, until just now
    when I looked it up, that the real part of a quaternion is often
    referred to as it's scalar part.
    That's a little odd, because I'm one of the probably very few people
    here who've actually made practical use of quaternions. I had to deal
    with data about spacecraft orientation that was stored as a quaternion,
    and convert between quaternions and corresponding Euler angles and
    Rotation matrices. However, a quaternion library was part of the
    standard toolkit for that project, which makes sense.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From BGB@cr88192@gmail.com to comp.lang.c on Tue Aug 11 14:54:11 2026
    From Newsgroup: comp.lang.c

    On 8/11/2026 10:17 AM, James Kuyper wrote:
    On 2026-08-10 21:44, BGB wrote:
    On 8/10/2026 7:03 PM, James Kuyper wrote:
    On 2026-08-10 18:31, BGB wrote:
    Snipped section included my epic fail at trying to use traditional
    style
    mathematical notation in a Usenet post...

    It was bugging me, by implying the conjugate was a scalar, where no, the >>>> conjugate is not a scalar...

    I'm not sure what you're saying. As far as C is concerned. complex types >>> are floating types (6.2.5p15), and therefore arithmetic types
    (6.2.5p23), and therefore scalar types (6.2.5p26) Therefore, a function
    that returns the conjugate of its argument would return a scalar type.

    I wrote:
    R^-1 = (R.r-R.i-R.j-R.k) / (R.r*R.r + R.i*R.i + R.j*R.j + R.k*R.k)

    The problem:
    (R.r-R.i-R.j-R.k)
    Should have been, say:
    (R.r - R.i*I - R.j*J - R.k*K)

    Which was bugging me, because either the former would be interpreted as
    meaning a scalar (or real-valued) result, or "R.i*R.i" as being
    negative, neither of which was true in the intended expression...

    I was confused because you were writing about complex numbers, mentioned
    that you had snipped some material, and then made a comment that I
    assumed, from context, was also about complex numbers. I did not realize
    that there was a context switch to quaternions inside the snipped material. In the unlikely event that that were added to C, quaternions would
    almost certainly be added as a new arithmetic (and therefore, scalar)
    type, by analogy with the complex types. I was unaware, until just now
    when I looked it up, that the real part of a quaternion is often
    referred to as it's scalar part.

    I wasn't the one who snipped it, but commented on it because (to me at
    least) it seemed like such a glaring notation screw up that I almost
    half expected to be called out on it.


    That's a little odd, because I'm one of the probably very few people
    here who've actually made practical use of quaternions. I had to deal
    with data about spacecraft orientation that was stored as a quaternion,
    and convert between quaternions and corresponding Euler angles and
    Rotation matrices. However, a quaternion library was part of the
    standard toolkit for that project, which makes sense.

    Yeah.

    In my case, I added them as an extension type in BGBCC along with
    traditional vectors and _Complex.



    Partly, this goes back to my more 3D engine programming days, where I
    had ended up using them for 3D skeletal animation math (though my first versions worked by interpolating 3x3 matrices, which was another pain,
    and inefficient, *).

    *1: Doesn't flow at uniform speed or maintain scale or orthogonality.
    This means, to interpolate between dissimilar 3D rotation matrices it
    was necessary to subdivide the interpolation and then re-normalize and
    fix-up orthogonality at each step.

    Another related animation format I had been using (known as "Valve SMD")
    had instead used yaw/pitch/roll for expressing bone rotations; which was inherently ill-behaved (if trying to interpolate these angles directly, results weren't very good; and it was possible to essentially gimbal
    lock the limb movements if the initial set of angles in the reference
    skeleton were not chosen well). Where, say, the skeleton specified an
    initial set of limb rotations which the vertex skinning would be applied relative to, and the animation rotations were relative to the base
    rotations of the skeleton in angle space.

    When I later did my own skeletal animation format, I promptly abandoned
    the use of angles for bone orientations. Though, as noted, initially
    used 3x3 matrices before later going to quats; initially had found 3x3 matrices as more intuitive. Though can note that one could discard one
    axis and express the matrix as 6 numbers by noting that Z = X % Y.

    I ended up switching mostly to quaternions here; which interpolate more nicely. Though still need to subdivide and renormalize for larger
    movements, and hack around the "720 degrees for a full rotation" quirk.


    In the first 3D engine, had also ended up implementing a rigid body
    physics engine, where they were also useful (for expressing things like rotation, angular velocity, etc).


    Though it didn't end up used much, as apart from in games like Half-Life
    2, where it was used as a bit of a gimmick, rigid body physics turns out
    to not be particular useful for typical first-person-shooter style
    movement or gameplay. Well, vs the Quake approach, where everything is basically sliding refrigerator-sized bounding
    axis-aligned-bounding-boxes. Though, sometimes Doom style cylinders are
    also useful, or one can use a definition where you have height and
    radius (like the cylinder) but then treat it as either a cylinder or
    bounding box depending on whichever is more convenient at that moment (typically a bounding box where the radius gives the min/max X/Y
    extents, height gives the Z extent relative to the origin which exists
    at floor level, with players having a view-height used to derive the
    camera position, ...).



    One of my own languages (BGBScript2) had then ended up with quaternions
    as a built-in type, partly as my second 3D engine was also using them
    for entity orientations (even if ironically it was using mostly
    billboard sprites for entities; mostly because 3D modeling and animation
    was a huge pain, but this was also partly a side-effect of me having
    written my own 3D modeling and animation tools, and I am not great with UI).

    They mostly replaced its predecessor's use of yaw/pitch/roll.


    Then, I now have a 3rd 3D engine, which ironically has partly started
    using 3D models again, though this time around had mostly been using a language known as SCAD to express them (with BGBCC having gained a SCAD converter, partly reusing the C parser and expression-optimizer steps as
    a makeshift interpreter to "compile" the SCAD models; partly as BGBCC's
    core is also used as an asset converter and asset-packing tool, partly
    as an outgrowth of it also serving the role of a "resource compiler", ...).

    Annoyingly though, SCAD lacks any ways to express texture-mapping or
    skeletal animation. I had debated adding these as informal extensions
    (but, then this breaks the ability to preview models in OpenSCAD, unless
    I were to essentially write a clone of this as well).

    Well, and as a worse bit of hackery, for animated CSG models (prior to implementing SCAD support in BGBCC, had been done CSG by hacking it onto
    an extended version of a 1980s style BASIC dialect (pros/cons vs SCAD).


    As can be noted, SCAD basically being a language for expressing CSG
    primitives and performing operations between them (union, difference,
    etc), to specify shapes.

    Internally, BGBCC's converter mostly works by first converting the
    abstract primitives into "brushes" (as a solid defined in terms of a collection of planes defining its outer boundaries). So, first you
    create large polygons, and then clip each polygon by all the planes for
    the brush (keeping only the interior parts).

    Then, identify overlapping brushes, and clip between them based on the
    sign of the brush. With SCAD it can get more complicated as you can also
    clip parts off a negative brushes in which point it no longer subtracts
    for this part, ... Getting some of this working correctly is still on a
    TODO list. It mostly works OK so long as one mostly sticks to unions.

    This latter part is mostly working in a vaguely similar way to the Quake
    BSP compiler.


    Though, maybe ironically, the 3rd engine was mostly back to specifying
    entity orientations as yaw or yaw/pitch/roll. But, mostly this is a case
    of, for something on the ground, you mostly just need a yaw angle.

    But, within the skeletal system, still uses quaternions for things like
    bone positioning and rotation math (though then uses transform matrices
    to project the bone-relative vertex coords into the final space).

    Note that its ways of expressing models are mostly by projecting the
    internal model into prebuilt vertex arrays that are cached for rendering
    (so typically rendering a model is just drawing the vertex arrays, or
    maybe rebuilding them if not already cached).


    Can also note in my 3rd 3D engine:
    Entities are using a height/radius system (like Doom).
    Except for when using CSG models, decided to give these more accurate collision handling.

    Though, I ended up using system for movement and collision detection
    (against the world) partly inspired by old NES era games:
    Rather than the slightly more expensive task of doing a bunch of box/box
    or box/plane handling (like in Quake), one can instead figure out which
    box points are along the forward direction of travel and then do point
    probes.

    At least with a voxel world, point-probing is cheap.


    Collision with CSG solids needs more complex handling though, but this
    is only needed if there is already a collision with the bounding volume
    of the CSG solid (though, in this case, they were mostly being treated
    as BREP solids, with the pre-cooked 3D models no longer storing the
    original CSG brushes; CSG brush checks are more computationally
    efficient than BREP though).

    Mostly in this engine, was used thus far for being able to stand on
    things like couches and dressers.


    If I were to re-add rigid body physics (unlikely ATM), this generally
    involves determining the intersection points between the solids, and
    then applying forces/torques based on the contact points.

    In the first 3D engine, didn't really use any 3rd party libraries, just
    sorta rolled my own.

    Conceptually it is not that difficult, but getting objects to stack in a stable way is harder than it may seem at first (the objects can never
    fully resolve the collisions, and if not handled well this can result in positive feedback loops and "random explosive acceleration"). Usual
    workaround was to apply dampening, and then to "lock" objects once
    velocity drops low enough (locked objects ignoring collision with other
    locked objects, but may unlock if acted on by an unlocked object with a
    force above a certain cut-off threshold).

    Was probably kinda moot though, there turned out to not be much need for object stacking.


    My initial motivation had mostly been "Half-Life 2", as when it came out (roughly around the time I finished high-school), this gimmick seemed
    more compelling.

    So, when my college-age self was off imitating Doom3's light/shadow
    system, had also wrote a mock up of Half-Life 2 style physics to go
    along with it.



    But, later realized both were mostly kinda needless overkill.

    Well, and even then, if I wanted to go back to real-time light and
    shadows, shadow-mapping is cheaper / higher performance than stencil
    shadows.

    Well, and the harder problem was usually more in trying to find any way
    to make this stuff "actually interesting".


    ...


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c on Tue Aug 11 13:47:33 2026
    From Newsgroup: comp.lang.c

    On 8/11/2026 8:17 AM, James Kuyper wrote:
    On 2026-08-10 21:44, BGB wrote:
    On 8/10/2026 7:03 PM, James Kuyper wrote:
    On 2026-08-10 18:31, BGB wrote:
    Snipped section included my epic fail at trying to use traditional
    style
    mathematical notation in a Usenet post...

    It was bugging me, by implying the conjugate was a scalar, where no, the >>>> conjugate is not a scalar...

    I'm not sure what you're saying. As far as C is concerned. complex types >>> are floating types (6.2.5p15), and therefore arithmetic types
    (6.2.5p23), and therefore scalar types (6.2.5p26) Therefore, a function
    that returns the conjugate of its argument would return a scalar type.

    I wrote:
    R^-1 = (R.r-R.i-R.j-R.k) / (R.r*R.r + R.i*R.i + R.j*R.j + R.k*R.k)

    The problem:
    (R.r-R.i-R.j-R.k)
    Should have been, say:
    (R.r - R.i*I - R.j*J - R.k*K)

    Which was bugging me, because either the former would be interpreted as
    meaning a scalar (or real-valued) result, or "R.i*R.i" as being
    negative, neither of which was true in the intended expression...

    I was confused because you were writing about complex numbers, mentioned
    that you had snipped some material, and then made a comment that I
    assumed, from context, was also about complex numbers. I did not realize
    that there was a context switch to quaternions inside the snipped material. In the unlikely event that that were added to C, quaternions would
    almost certainly be added as a new arithmetic (and therefore, scalar)
    type, by analogy with the complex types. I was unaware, until just now
    when I looked it up, that the real part of a quaternion is often
    referred to as it's scalar part.
    That's a little odd, because I'm one of the probably very few people
    here who've actually made practical use of quaternions. I had to deal
    with data about spacecraft orientation that was stored as a quaternion,
    and convert between quaternions and corresponding Euler angles and
    Rotation matrices. However, a quaternion library was part of the
    standard toolkit for that project, which makes sense.

    quaternion are very useful for such things. Avoiding gimbal lock?
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c on Tue Aug 11 13:49:37 2026
    From Newsgroup: comp.lang.c

    On 8/11/2026 6:46 AM, Dan Cross wrote:
    In article <115dot7$3ihmr$1@dont-email.me>,
    James Kuyper <jameskuyper@alumni.caltech.edu> wrote:
    On 2026-08-10 18:31, BGB wrote:
    Snipped section included my epic fail at trying to use traditional
    style
    mathematical notation in a Usenet post...

    It was bugging me, by implying the conjugate was a scalar, where no, the >>> conjugate is not a scalar...

    I'm not sure what you're saying. As far as C is concerned.

    Was it not clear to you that he was referring to the definition
    of a complex conjugate, in the mathematical sense?

    The conjugate of a complex number is also a complex number, and
    it is common in elementary mathematics to regard such numbers as
    a vector (specifically a pair) consisting of a real component,
    and an imaginary component. Some other fields think of complex
    numbers as scalars, but I would expect the person you replied to
    to think of a complex number z=a+bi as an ordered pair, <a,b>,
    where a,b are real numbers and where "a" is the value of the
    real component, and "b" is the (real) factor of the imaginary
    component. The complex conjugate of z is then z*=a-bi=<a,-b>,
    is also a vector.

    simply negate the imaginary part for the conjugate.



    This is totally independent of how C defines things; because C
    defines its complex type as a "scalar type" does not mean that
    in the mathematical sense, complex numbers cannot be thought of
    as vectors. Besides, math was here first.

    complex types
    are floating types (6.2.5p15), and therefore arithmetic types
    (6.2.5p23), and therefore scalar types (6.2.5p26) Therefore, a function
    that returns the conjugate of its argument would return a scalar type.

    This is exactly the danger of an overly pedantic reading: it
    leads to attempts to apply one's knowledge of some domain
    (such as C) to things outside that domain (such as mathematics).
    Being overly rigid in one's thinking and interpretations is not
    a sign of expertise, but rather, of the inability to abstract
    appropriately.

    - Dan C.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c on Tue Aug 11 14:01:08 2026
    From Newsgroup: comp.lang.c

    On 8/11/2026 6:45 AM, Ross Finlayson wrote:
    [...]
    So, "tensor" used in the field like "we have a tensor machine"
    usually enough is gussied-up "we have a system of linear invariants
    according to a vector model", since "tensor" is a bit wider itself.

    It is what it does, ....

    I tend to like n-ary vectors in an n-ary vector field. Fwiw, here is an example animation I made, along with the MIDI music:

    https://youtu.be/HwIkk9zENcg
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Wed Aug 12 03:36:45 2026
    From Newsgroup: comp.lang.c

    On Tue, 11 Aug 2026 14:54:11 -0500, BGB wrote:

    Partly, this goes back to my more 3D engine programming days, where
    I had ended up using [quaternions] for 3D skeletal animation math
    (though my first versions worked by interpolating 3x3 matrices,
    which was another pain, and inefficient, *).

    *1: Doesn't flow at uniform speed or maintain scale or
    orthogonality. This means, to interpolate between dissimilar 3D
    rotation matrices it was necessary to subdivide the interpolation
    and then re-normalize and fix-up orthogonality at each step.

    Also prone to accumulated rounding errors.

    There was an item in one of the rCLGraphics GemsrCY books about a
    numerical technique for fixing this up every N rotation steps, for a
    suitable choice of N. You need to renormalize the matrix so its
    determinant becomes 1. There is a cost to this, which is why you might
    not want to do it after every rotation step.

    I ended up switching mostly to quaternions here; which interpolate
    more nicely. Though still need to subdivide and renormalize for
    larger movements, and hack around the "720 degrees for a full
    rotation" quirk.

    I think that 720-# range is not considered a bug, itrCOs a feature ;).

    Basically, it eases the job of interpolating full-circle rotations,
    since you have the leeway to start at any point without a
    discontinuity.

    Annoyingly though, SCAD lacks any ways to express texture-mapping or
    skeletal animation. I had debated adding these as informal
    extensions (but, then this breaks the ability to preview models in
    OpenSCAD, unless I were to essentially write a clone of this as
    well).

    The big 3D studios (Pixar etc) have gone through a number of different
    standard interchange formats for expressing this sort of information.
    The current darling seems to be rCLUniversal Scene DescriptionrCY or USD.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From BGB@cr88192@gmail.com to comp.lang.c on Wed Aug 12 01:24:32 2026
    From Newsgroup: comp.lang.c

    On 8/11/2026 10:36 PM, Lawrence DrCOOliveiro wrote:
    On Tue, 11 Aug 2026 14:54:11 -0500, BGB wrote:

    Partly, this goes back to my more 3D engine programming days, where
    I had ended up using [quaternions] for 3D skeletal animation math
    (though my first versions worked by interpolating 3x3 matrices,
    which was another pain, and inefficient, *).

    *1: Doesn't flow at uniform speed or maintain scale or
    orthogonality. This means, to interpolate between dissimilar 3D
    rotation matrices it was necessary to subdivide the interpolation
    and then re-normalize and fix-up orthogonality at each step.

    Also prone to accumulated rounding errors.

    There was an item in one of the rCLGraphics GemsrCY books about a
    numerical technique for fixing this up every N rotation steps, for a
    suitable choice of N. You need to renormalize the matrix so its
    determinant becomes 1. There is a cost to this, which is why you might
    not want to do it after every rotation step.


    Yes, it is a pain...


    I tended to need to re-normalize often, but for skeletal animation, if
    only encoding the reference positions at keyframes, there is often a significant divergence in the positions being interpolated.

    One strategy was to estimate a midpoint, and then use successive
    averaging to find the interpolated matrix, say:
    matC0a=MatFixup(0.625*matA+0.375*matB); //(5/8)*A + (3/8)*B
    matC0b=MatFixup(0.375*matA+0.625*matB); //(3/8)*A + (5/8)*B
    matC=MatFixup(0.5*matC0a + 0.5*matC0b); //Average

    Where this approach can have "slightly less" path distortion than
    directly averaging and renormalizing.

    Then, the fraction is represented, say, as 8 bits:
    LerpMatrix(initA, initB, frac)
    if(MatCloseEnough(initA, initB))
    {
    //say, can lerp if dot products are greater than 0.7 or so.
    C=((1-frac)*initA)+(frac*initB);
    C=MatFixup(C);
    return(C);
    }
    C=MatMidpoint(initA, initB);
    if(frac<0.5)
    return(LerpMatrix(initA, C, frac*2));
    return(LerpMatrix(C, initB, (frac-0.5)*2));


    But, this approach still has failure cases (will break if the two are
    180 degrees apart, so the path travels through the origin).

    But, yeah, not really worth it to try to interpolate matrices.



    I ended up switching mostly to quaternions here; which interpolate
    more nicely. Though still need to subdivide and renormalize for
    larger movements, and hack around the "720 degrees for a full
    rotation" quirk.

    I think that 720-# range is not considered a bug, itrCOs a feature ;).

    Basically, it eases the job of interpolating full-circle rotations,
    since you have the leeway to start at any point without a
    discontinuity.


    It is a quirk that sometimes needs to be worked around.

    Say, if lerping between two points that are nearly 360 degrees apart,
    then, the interpolation will tend to perform an unexpected full-rotation.

    Granted, if the point is too far away one can take the inverse and get a
    point that is closer and still represents the same apparent 3D rotation
    (and if it then suddenly snaps orientation by 360 degrees at the end,
    this is invisible).

    In most other case, yes, this is less of an issue.


    In general, there are still less bad than the other options though...

    Like, mostly:
    Interpolate, re-normalize, and call it done.


    Annoyingly though, SCAD lacks any ways to express texture-mapping or
    skeletal animation. I had debated adding these as informal
    extensions (but, then this breaks the ability to preview models in
    OpenSCAD, unless I were to essentially write a clone of this as
    well).

    The big 3D studios (Pixar etc) have gone through a number of different standard interchange formats for expressing this sort of information.
    The current darling seems to be rCLUniversal Scene DescriptionrCY or USD.

    Very quick look:
    This seems like a mesh-based format for import/export to from 3D
    modeling software...

    This is *very* different from what SCAD is.

    I have found I would rather not use point-and-click tools for 3D
    modeling (weird, I know).



    In SCAD, the OpenSCAD UI isn't a 3D modeler, rather it is more just a
    viewer and converter. To make the geometry itself, you edit it in a text editor. In OpenSCAD you can also process it and export it as an STL or
    similar (mostly intended for 3D printing).



    Though, not like SCAD is perfect either, I probably would have done some things differently.

    Typical way it does things is like, say (red box with blue ball on top):
    union() {
    color("red")
    translate([-25,-25,0])
    cube([50,50,50]);
    color("blue")
    translate([0,0,75])
    sphere(50);
    }

    Though, say, OpenSCAD is fairly particular, you can't really add
    anything to the language without breaking OpenSCAD's ability to render it.

    Also it has no concept of integer math or bitwise operations (very
    annoying, like one can't really write functions for text glyphs or
    7-segment displays or similar in SCAD as a result).


    Within the existing language, it scales poorly in some other areas, like
    for example, expressing something like a 20-sided dice in SCAD (with
    numbers on all of the faces) would be a massive pain, and one would need
    a more generally capable interpreter for this (say, to specify each dice
    face and also engrave a number onto each face).


    ...


    Typically, it operated on linear translations, and specified rotations
    as angles relative to each axis.


    In CSG-BASIC, the CSG solids were treated as objects that could go into variables...

    Where, CSG-BASIC resembled early 1980s style BASIC, but with dynamic
    scoping, and CSG. And, wonky, as BASIC wasn't really meant for this.


    I would likely do something similar if I did a more general CSG
    language, maybe moving it is a more JS-like direction (but, assuming
    here something still kinda SCAD like in some ways):
    var obj1=
    csgTranslate([-25,-25,0],
    [csgCube([25,25,25])]);
    var obj2=
    csgTranslate([0,0,75],
    [csgSphere(50)]);
    var obj3=csgUnion([obj1, obj2]);

    Then, for example:
    function horzSeg()
    {
    return csgUnion([
    csgTranslate([-25,-5,-4],
    [cube([50,10,5])]),
    csgTranslate([-25,0,-4],
    csgRotate([0,0,45],
    csgTranslate([-5,-5,0],
    cube([10,10,5])))),
    csgTranslate([25,0,-4],
    csgRotate([0,0,45],
    csgTranslate([-5,-5,0],
    cube([10,10,5]))))
    ]);
    }
    function vertSeg()
    { return csgRotate([0,0,90], horzSeg()); }
    function sevenSeg(segsmask)
    {
    var seglist=[null,null,null,null,null,null,null];
    if(segmask&1)
    seglist[0]=translate([0, 50, 0], horzSeg());
    if(segmask&2)
    seglist[1]=translate([25, 25, 0], vertSeg());
    if(segmask&4)
    seglist[2]=translate([25, -25, 0], vertSeg());
    if(segmask&8)
    seglist[3]=translate([0, -50, 0], horzSeg());
    if(segmask&16)
    seglist[4]=translate([-25, -25, 0], vertSeg());
    if(segmask&32)
    seglist[5]=translate([-25, 25, 0], vertSeg());
    if(segmask&64)
    seglist[6]=translate([0, 0, 0], horzSeg());
    return(csgUnion(seglist, color: "red"));
    }


    Might diverge more, say:
    csgAabb(mins: [-25,-5,-4], maxs: [25,5,1]);
    Which can reduce the number of translation steps needed.

    Or, maybe allow raw brushes, say:
    csgBrush([
    [ 0 , 0 ,-1, 4],
    [ 0 , 0 , 1, 1],
    [ 0 , 1 , 0, 5],
    [ 0 ,-1 , 0, 5],
    [-0.707, 0.707, 0,30],
    [-0.707,-0.707, 0,30],
    [ 0.707, 0.707, 0,30],
    [ 0.707,-0.707, 0,30]
    ]);
    Say, to express something shaped like a 7-segment bar via raw plane normals.


    Possibly, could support "color", "texture", "bone", etc, as named
    parameters to csgUnion or similar, as this is essentially how I had
    approached it in CSG-BASIC.


    In any case, would likely want to stick to a format where one can
    express things in a text editor.



    Granted, not necessarily a good way to do natural looking humanoids or similar.

    But, at one point (in both SCAD and CSG-BASIC), made a model of a guy
    that kinda resembles one of the characters from the "Money for Nothing"
    video. CSG can do these kind of shapes.

    Maybe if pushed harder, could do characters in a ReBoot like style.
    But, admittedly, humanoids isn't really the strong area of CSG.


    Well, can also note that admittedly it is a bit of a pain to write a walk-cycle or similar by hand-typing the numbers.

    Like, even recreating animation like in that video wouldn't be
    particularly easy (though the video was strategic, you don't see the characters legs while walking, so they skipped needing walk cycles).

    But, yeah...


    ...



    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Wed Aug 12 07:47:16 2026
    From Newsgroup: comp.lang.c

    On Wed, 12 Aug 2026 01:24:32 -0500, BGB wrote:

    Say, if lerping between two points that are nearly 360 degrees
    apart, then, the interpolation will tend to perform an unexpected full-rotation.

    Been there, done that, with actual 3D modelling/animation software
    (Blender).

    Takes some careful placement of extra keyframes to get the rotation to
    come out right ;).

    I have found I would rather not use point-and-click tools for 3D
    modeling (weird, I know).

    CG is very much a mix of art and science. You canrCOt be very effective
    if you are only good on one side.

    Blender includes a feature called rCLGeometry NodesrCY, sort of a
    graphical programming language for geometry-generation/manipulation.

    Do you remember Alan TuringrCOs paper on reaction/diffusion systems,
    where he came up with a mathematical theory on how a symmetrical clump
    of cells making up a fertilized embryo can decide which is head, which
    is tail, which is left and which is right? Here <https://www.youtube.com/watch?v=RSpkkuOOtBw> is a tutorial on how to
    implement such a system to produce some crazy patterns.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c on Wed Aug 12 12:52:52 2026
    From Newsgroup: comp.lang.c

    On 8/12/2026 12:47 AM, Lawrence DrCOOliveiro wrote:
    On Wed, 12 Aug 2026 01:24:32 -0500, BGB wrote:

    Say, if lerping between two points that are nearly 360 degrees
    apart, then, the interpolation will tend to perform an unexpected
    full-rotation.

    Been there, done that, with actual 3D modelling/animation software
    (Blender).

    Takes some careful placement of extra keyframes to get the rotation to
    come out right ;).

    I have found I would rather not use point-and-click tools for 3D
    modeling (weird, I know).

    CG is very much a mix of art and science. You canrCOt be very effective
    if you are only good on one side.

    Blender includes a feature called rCLGeometry NodesrCY, sort of a
    graphical programming language for geometry-generation/manipulation.

    Geometry Nodes in blender are okay, especially with instances. For
    instance one of my script dumps out points. Each point has a scale and a rotation. The nodes tap into that. Here is an example result:

    https://skfb.ly/pzTEC

    However, the script lang is slow, its kind of a "hog", the blender.
    Using C or C++ for generating the geometry is a lot faster. no big ass
    pig IDE to slog around in. But, Blender is pretty nice. But. Its a bit
    fat...


    Do you remember Alan TuringrCOs paper on reaction/diffusion systems,
    where he came up with a mathematical theory on how a symmetrical clump
    of cells making up a fertilized embryo can decide which is head, which
    is tail, which is left and which is right? Here <https://www.youtube.com/watch?v=RSpkkuOOtBw> is a tutorial on how to implement such a system to produce some crazy patterns.

    I have a way for DLA to not use any random numbers. Don't really want to publish my technique yet, but here is an example:

    NO random numbers were used:

    https://youtu.be/mqYBMuvVJI8



    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c on Wed Aug 12 12:56:38 2026
    From Newsgroup: comp.lang.c

    On 8/12/2026 12:52 PM, Chris M. Thomasson wrote:
    On 8/12/2026 12:47 AM, Lawrence DrCOOliveiro wrote:
    On Wed, 12 Aug 2026 01:24:32 -0500, BGB wrote:

    Say, if lerping between two points that are nearly 360 degrees
    apart, then, the interpolation will tend to perform an unexpected
    full-rotation.

    Been there, done that, with actual 3D modelling/animation software
    (Blender).

    Takes some careful placement of extra keyframes to get the rotation to
    come out right ;).

    I have found I would rather not use point-and-click tools for 3D
    modeling (weird, I know).

    CG is very much a mix of art and science. You canrCOt be very effective
    if you are only good on one side.

    Blender includes a feature called rCLGeometry NodesrCY, sort of a
    graphical programming language for geometry-generation/manipulation.

    Geometry Nodes in blender are okay, especially with instances. For
    instance one of my script dumps out points. Each point has a scale and a rotation. The nodes tap into that. Here is an example result:

    https://skfb.ly/pzTEC

    However, the script lang is slow, its kind of a "hog", the blender.
    Using C or C++ for generating the geometry is a lot faster. no big ass
    pig IDE to slog around in. But, Blender is pretty nice. But. Its a bit fat...


    Do you remember Alan TuringrCOs paper on reaction/diffusion systems,
    where he came up with a mathematical theory on how a symmetrical clump
    of cells making up a fertilized embryo can decide which is head, which
    is tail, which is left and which is right? Here
    <https://www.youtube.com/watch?v=RSpkkuOOtBw> is a tutorial on how to
    implement such a system to produce some crazy patterns.

    I have a way for DLA to not use any random numbers. Don't really want to publish my technique yet, but here is an example:

    NO random numbers were used:

    https://youtu.be/mqYBMuvVJI8




    Here is one with the main field turned off:

    https://youtu.be/abQDYGT_cIk
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Thu Aug 13 02:16:06 2026
    From Newsgroup: comp.lang.c

    On Wed, 12 Aug 2026 12:52:52 -0700, Chris M. Thomasson wrote:

    Geometry Nodes in blender are okay, especially with instances. For
    instance one of my script dumps out points. Each point has a scale
    and a rotation. The nodes tap into that. Here is an example result:

    https://skfb.ly/pzTEC

    However, the script lang is slow, its kind of a "hog", the blender.
    Using C or C++ for generating the geometry is a lot faster. no big
    ass pig IDE to slog around in.

    DoesnrCOt look very complicated. Are you just instancing a basic shape
    on points from a bunch of mesh lines?

    But, Blender is pretty nice. But. Its a bit fat...

    ItrCOs a lot smaller download than Autodesk Maya or proprietary
    alternatives like that.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c on Wed Aug 12 21:04:53 2026
    From Newsgroup: comp.lang.c

    On 8/12/2026 7:16 PM, Lawrence DrCOOliveiro wrote:
    On Wed, 12 Aug 2026 12:52:52 -0700, Chris M. Thomasson wrote:

    Geometry Nodes in blender are okay, especially with instances. For
    instance one of my script dumps out points. Each point has a scale
    and a rotation. The nodes tap into that. Here is an example result:

    https://skfb.ly/pzTEC

    However, the script lang is slow, its kind of a "hog", the blender.
    Using C or C++ for generating the geometry is a lot faster. no big
    ass pig IDE to slog around in.

    DoesnrCOt look very complicated. Are you just instancing a basic shape
    on points from a bunch of mesh lines?

    Yeah. I created instancing data in my python scripts. Then I actually
    instance them (icospheres iirc) using geometry nodes. This is for
    blender. Instancing in my, say, my modern opengl/dx12 work is way more efficient.

    Other times I just plot the damn triangles. Fwiw, this was made in
    blender using one of my scripts. You should be able to navigate it:

    https://skfb.ly/pyxCL



    But, Blender is pretty nice. But. Its a bit fat...

    ItrCOs a lot smaller download than Autodesk Maya or proprietary
    alternatives like that.

    Yeah.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From BGB@cr88192@gmail.com to comp.lang.c on Wed Aug 12 23:07:35 2026
    From Newsgroup: comp.lang.c

    On 8/12/2026 2:52 PM, Chris M. Thomasson wrote:
    On 8/12/2026 12:47 AM, Lawrence DrCOOliveiro wrote:
    On Wed, 12 Aug 2026 01:24:32 -0500, BGB wrote:

    Say, if lerping between two points that are nearly 360 degrees
    apart, then, the interpolation will tend to perform an unexpected
    full-rotation.

    Been there, done that, with actual 3D modelling/animation software
    (Blender).

    Takes some careful placement of extra keyframes to get the rotation to
    come out right ;).

    I have found I would rather not use point-and-click tools for 3D
    modeling (weird, I know).

    CG is very much a mix of art and science. You canrCOt be very effective
    if you are only good on one side.

    Blender includes a feature called rCLGeometry NodesrCY, sort of a
    graphical programming language for geometry-generation/manipulation.

    Geometry Nodes in blender are okay, especially with instances. For
    instance one of my script dumps out points. Each point has a scale and a rotation. The nodes tap into that. Here is an example result:

    https://skfb.ly/pzTEC

    However, the script lang is slow, its kind of a "hog", the blender.
    Using C or C++ for generating the geometry is a lot faster. no big ass
    pig IDE to slog around in. But, Blender is pretty nice. But. Its a bit fat...


    Raw C is a bit poor of an interface for CSG, even if it is powerful.


    A specialized language like SCAD works here, but the problem in this
    case is flexibility and generality.

    Say, if you want an icosahedron, there should be some practical way in-language to construct it. And if you want to put numbers on each
    face, likewise.


    I am starting to run into a problem where, some of the sorts of stuff I
    want to do are effectively more complex than what a language like SCAD
    can deal with effectively.

    It has various things built-in, but no ability to specify or construct generalized brushes.

    And, as can be noted:
    No support for integer or bitwise operations;
    Only weak/inflexible support for looping or conditional structures.

    Or, if used for 3D graphics:
    No way to specify texture mapping (basic colors only);
    No way to attach geometry to a skeleton;
    ...


    Though, it is unclear what a more generalized language should look like...

    But, things it should *NOT* look like:
    Traditional point-and-click 3D modeling;
    Doesn't matter if Blender, or SolidWorks, or FreeCAD, or whatever.
    Graphical / GUI based "tile programming" or "nodes".

    I would much rather stay with some sort of text-based language that can
    be edited in a normal text-editor, and does not depend on some
    particular program for the entirety of its existence.


    As for CSG vs mesh modeling:

    CSG: Specifies solid shapes, which is more useful if 3D physics needs to
    get involved, or you want to turn it into something you can 3D print.

    Meshes: More popular/traditional for 3D graphics, and more easily
    achieves natural shapes. But, worse suited to any sort of physical
    simulation, particularly if using non-closed meshes.


    In some systems, there were mesh-based objects or worlds where each
    primitive (triangle/quad/polygon) is treated as its own solid object for
    sake of collision detection.

    Some examples:
    Half-Life 2: Often used CSG brushes only for the rough map shape, and a
    lot of meshes for internal things, treating each polygon as a (fairly
    thin) collision object.

    Nintendo and Sega also liked using this approach in a lot of their games (building worlds out of "solid" polygons).


    Some problems:
    Depending on physics engine, much weaker against "bullet through paper" issues, where a fast moving object effectively flies straight through a
    wall or similar because in both the before and after time-step, there
    was no collision (this is much less likely to happen if the "wall" is a
    single big chunk of solid space).

    One well-known glitch (particularly in Source Engine games) where a
    ragdoll could get stuck with part above and part below the "ground" or similar, and then start convulsing violently.

    This being because to move either way (to resolve the collision), limbs
    will need to move through the solid ground layer.


    If animating characters as CSG though, a few possibilities come up:
    Each solid is attached to a bone and then CSG'ed individually, animating
    by transforming the resulting mesh (and allowing non-colliding
    intersections between limbs on the same character, otherwise animation
    would be nearly impossible).

    Or, alternatively, animating by moving the CSG solids themselves and
    then redoing the CSG math for every scene/pose rendered.

    But, yeah, achieving a look similar to ReBoot via CSG could very well be possible. If wanting a more modern / "organic" look, this doesn't map as
    well to CSG, but as I see it, isn't always necessary or desirable (the obsession among AAA gaming of making everything look "photorealistic"
    has become in some sense misguided).




    Do you remember Alan TuringrCOs paper on reaction/diffusion systems,
    where he came up with a mathematical theory on how a symmetrical clump
    of cells making up a fertilized embryo can decide which is head, which
    is tail, which is left and which is right? Here
    <https://www.youtube.com/watch?v=RSpkkuOOtBw> is a tutorial on how to
    implement such a system to produce some crazy patterns.

    I have a way for DLA to not use any random numbers. Don't really want to publish my technique yet, but here is an example:

    NO random numbers were used:

    https://youtu.be/mqYBMuvVJI8




    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Thu Aug 13 05:00:09 2026
    From Newsgroup: comp.lang.c

    On Wed, 12 Aug 2026 23:07:35 -0500, BGB wrote:

    I am starting to run into a problem where, some of the sorts of
    stuff I want to do are effectively more complex than what a language
    like SCAD can deal with effectively.

    It has various things built-in, but no ability to specify or
    construct generalized brushes.

    Immediately IrCOm thinking rCLmodelling/rendering engine with Python APIrCY.

    May be worth looking at Blender for this. Its Python API is probably
    the most extensive of any content-creation app.

    As for CSG vs mesh modeling:

    CSG: Specifies solid shapes, which is more useful if 3D physics
    needs to get involved, or you want to turn it into something you can
    3D print.

    Meshes: More popular/traditional for 3D graphics, and more easily
    achieves natural shapes. But, worse suited to any sort of physical simulation, particularly if using non-closed meshes.

    Blender has both.

    But, yeah, achieving a look similar to ReBoot via CSG could very
    well be possible. If wanting a more modern / "organic" look, this
    doesn't map as well to CSG, but as I see it, isn't always necessary
    or desirable (the obsession among AAA gaming of making everything
    look "photorealistic" has become in some sense misguided).

    Photorealism seems to be routine and no longer quite as exciting.

    So now the new thing (or one new thing) is starting with a 2D
    animation style and adding some 3D elements to it <https://studio.blender.org/projects/singularity/>.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From BGB@cr88192@gmail.com to comp.lang.c on Thu Aug 13 04:37:29 2026
    From Newsgroup: comp.lang.c

    On 8/13/2026 12:00 AM, Lawrence DrCOOliveiro wrote:
    On Wed, 12 Aug 2026 23:07:35 -0500, BGB wrote:

    I am starting to run into a problem where, some of the sorts of
    stuff I want to do are effectively more complex than what a language
    like SCAD can deal with effectively.

    It has various things built-in, but no ability to specify or
    construct generalized brushes.

    Immediately IrCOm thinking rCLmodelling/rendering engine with Python APIrCY.

    May be worth looking at Blender for this. Its Python API is probably
    the most extensive of any content-creation app.

    As for CSG vs mesh modeling:

    CSG: Specifies solid shapes, which is more useful if 3D physics
    needs to get involved, or you want to turn it into something you can
    3D print.

    Meshes: More popular/traditional for 3D graphics, and more easily
    achieves natural shapes. But, worse suited to any sort of physical
    simulation, particularly if using non-closed meshes.

    Blender has both.


    I wouldn't want to make things dependent on Blender...

    Blender is a pretty big / heavyweight tool; and depending on Blender and
    Python is not exactly a small dependency.

    Like, my existing pipeline doesn't already depend on Blender, and I have
    no reason to add it as a dependency.



    For SCAD, was able to shove a converter into BGBCC mostly reusing the C
    parser as a SCAD parser. Even if there were syntactic differences, it
    was "close enough", and BGBCC already included a makeshift AST-level interpreter.


    If doing a standalone thing, would want to do it differently though. I
    have an experiment for a small JavaScript style interpreter. It was
    partly reused as a basis when starting to write a GLSL compiler.

    Could also be modified either into a SCAD interpreter, or possibly for a JS/SCAD hybrid.

    I might go this route if I wanted to add similar functionality into my
    BT3 engine (not going to copy BGBCC's C parser and similar over, that is
    also too big of a chunk of code to justify copy/pasting for this). Made
    sense in BGBCC though since it already had a C parser and the syntax was "close enough" to what the parser could already deal with.


    Though, it is a question of if I do something custom, how closely to
    stick to SCAD, vs how much to diverge. One option could be to mostly
    keep the same basic notation and structure as SCAD, but then extend it
    with some more JavaScript-like features.


    I would have to decide on the syntax. The BT3 engine already has some
    CSG code, and this was the source of what I had copied into BGBCC for
    its converter.

    Though, the BT3 engine had used a makeshift language I called CSG-BASIC,
    which leaves something to be desired.

    The CSG-BASIC syntax was more like:
    LET obj1 = (CSGAABB mins:[-10,-10,-10], maxs:[10,10,10])
    LET obj2 = (CSGSPHERE radius:5, origin:[0,0,15])
    LET obj3 = (CSGUNION obj1, obj2)
    RETURN obj3

    With control flow more like:
    LABEL1:
    ...
    RETURN
    ...
    GOSUB LABEL1
    Well, and:
    IF (cond) THEN command
    IF (cond) GOTO label
    ...

    Where, in this case (COMMAND args...) would evaluate the command and
    return its value as an expression (for commands that could be evaluated
    as expressions).

    Also it had a quirk that when inside of a "GOSUB" call, LET could create variables inside of a local dynamic frame rather than the toplevel
    (simple assignment would assign an existing variable, whereas LET could
    create a variable if it didn't already exist).

    Likewise:
    LET var = (GOSUB label var1:val1, var2:val2)
    Would function as a makeshift function call, binding the named variables
    in the callee's dynamic frame.


    Rationale was mostly that I could fit the whole parser + interpreter in
    around 2000 lines of C (whereas for an interpreter for a JavaScript
    style language (though, can be done in around 1000 lines if limiting the
    scope closer to something like AppleSoft BASIC; with much of the
    remaining 1000 lines being stuff it needed for the CSG support), it
    needs closer to around 6000 lines of C).

    Things like the wonky subroutine call mechanism was mostly because that
    was what I could do in the least amount of code (rather than what made
    sense for "good" language design).

    Also it was originally written as a very quick/dirty scripting language
    for the BT3 engine (and a similar language exists in my TestKern OS,
    albeit without the CSG features).



    Major difference vs this and a JS variant is that JS needs an AST parser
    and AST walker and similar, whereas with BASIC it is mostly possible to resolve tokens into index numbers and use tokens to drive the
    interpreter (and can use a simpler tokenizer, ...).

    Note that LOC cost here also includes tokenizer, dynamic typesystem, and memory management stuff (would be less if these were not counted).

    I didn't count a lot of the math code though, or the 3D model load/save
    code (these were counted as part of the BT3 engine itself, rather than
    part of CSG-BASIC).



    When I did CSG-BASIC though. I already had some bits of CSG code around
    as some past projects had used CSG, but in this case I had modeled it to support local hierarchical transformation of the brush models (which
    were now organized into a tree rather than a flat list).

    Though, another option could be instead extending CSG-BASIC with more "Structured-BASIC" like functionality (like QBasic or VisualBasic).



    Or, a 3rd option could be to do something similar, but go over to a Lisp dialect (an S-Expression parser/walker can also be expressed in a
    relatively modest amount of code).


    Mostly a matter of which route is "better".

    ...



    Well, going back a ways, an older format had represented entities and
    CSG brushes with a notation like:
    {
    "classname" "func_button"
    ...
    {
    ( x0 y0 z0 ) ( x1 y1 z1 ) ( x2 y2 z2 ) texname \
    [ sx sy sz so ] [ tx ty tz to ]
    ...
    }
    }
    Note, slash and linebreak because of word-wrap, original format has it
    all on one line.


    But, at its core, similar stuff...
    Would give planes as 3 vertices, though the vertices themselves didn't
    really matter as much, they merely gave 3 points on a plane.

    Or, at least this was one variant, there were a bunch of different
    variants of the format that diverged in various ways (like how exactly
    they specified the plane and texture orientation).

    Format wasn't very dynamic, mostly used to specify world maps.


    But, if used for CSG modeling it isn't *that* different.
    Even if now you need to throw an interpreter onto it to build the list
    of brushes.


    But, yeah, achieving a look similar to ReBoot via CSG could very
    well be possible. If wanting a more modern / "organic" look, this
    doesn't map as well to CSG, but as I see it, isn't always necessary
    or desirable (the obsession among AAA gaming of making everything
    look "photorealistic" has become in some sense misguided).

    Photorealism seems to be routine and no longer quite as exciting.

    So now the new thing (or one new thing) is starting with a 2D
    animation style and adding some 3D elements to it <https://studio.blender.org/projects/singularity/>.


    One interesting style IMO was a game known as "Chants of Sennaar"...

    It basically used a limited number of colors per-area, with basic
    shading, and relatively basic character designs (no visible faces, no
    voice acting or other flourishes, ...). Each area would have its own
    color palette.

    Or, another example being "Untitled Goose Game" where the player plays
    as a Goose that goes around and messes with people. Nearly everything in
    the game is fairly simplistic, characters mostly lack faces, and most of
    the graphics are flat-shaded (some textures may be used, but in a
    simplistic way that doesn't break from the flat-shaded look).


    Partly for related reasons (and partly for the lack of texture-map
    support in the SCAD format), most of the 3D models I made for my BT3
    engine were flat shaded as well.

    Apart from CSG-BASIC having the option of using textures, but most of
    the static models were SCAD. For now, CSG-BASIC just being needed for
    the models with skeletal animation.


    Well, and for my 3D model of a guy inspired by the general design of the skinny guy in the "Money for Nothing" video, I also still went for flat shading.

    Though, partly I originally wrote the model in SCAD and then transcribed
    it to CSG-BASIC.


    Also rather than specifying texture projection per-face, it was mostly specified with a mapping style. Like the texture would be mapped to the
    inside of a virtual cube or sphere or similar, and then the normal plane normal and vertex coords would be used to figure out the texture coords.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c on Thu Aug 13 14:36:14 2026
    From Newsgroup: comp.lang.c

    On 8/13/2026 2:37 AM, BGB wrote:
    [...]

    Fwiw, I made this in OpenSCAD, its pretty nice. openscad Almost reminds
    me of povray...

    https://skfb.ly/oqQEV


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Thu Aug 13 23:44:30 2026
    From Newsgroup: comp.lang.c

    On Thu, 13 Aug 2026 04:37:29 -0500, BGB wrote:

    On 8/13/2026 12:00 AM, Lawrence DrCOOliveiro wrote:

    On Wed, 12 Aug 2026 23:07:35 -0500, BGB wrote:

    As for CSG vs mesh modeling:

    CSG: Specifies solid shapes, which is more useful if 3D physics
    needs to get involved, or you want to turn it into something you
    can 3D print.

    Meshes: More popular/traditional for 3D graphics, and more easily
    achieves natural shapes. But, worse suited to any sort of physical
    simulation, particularly if using non-closed meshes.

    Blender has both.

    I wouldn't want to make things dependent on Blender...

    ItrCOs open source. The copyright is owned by a nonprofit foundation.
    ThererCOs no legal way that it could be swallowed up by any for-profit corporation. You are free to do what you want with the source code.

    Blender is a pretty big / heavyweight tool; and depending on Blender
    and Python is not exactly a small dependency.

    Blender is more lightweight than many alternatives, as I already
    pointed out. Everybody already has Python on their systems for other
    (very good) reasons, why not take advantage of that?

    Blender can be run in batch mode, under the control of a script
    which feeds it Python code to execute etc.

    There is also an option (marked as rCLexperimentalrCY in the Blender
    source tree) to build Blender as a set of Python modules.

    Like, my existing pipeline doesn't already depend on Blender, and I
    have no reason to add it as a dependency.

    It adds new capabilities you didnrCOt have before. Where else are you
    going to get anything similar?

    HererCOs an example from the early days of Geometry Nodes <https://www.youtube.com/watch?v=io_x3IqOndE>: combining a few
    hand-modelled pieces to create buildings of arbitrary complexity.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c on Thu Aug 13 18:50:05 2026
    From Newsgroup: comp.lang.c

    On 8/13/2026 4:44 PM, Lawrence DrCOOliveiro wrote:
    [...]

    Blender is pretty nice. But, its a bit large. Anyway, matter not in a
    sense. Its a tool. And it fun to program in Python for it.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Fri Aug 14 02:41:20 2026
    From Newsgroup: comp.lang.c

    On Thu, 13 Aug 2026 18:50:05 -0700, Chris M. Thomasson wrote:

    Blender is pretty nice. But, its a bit large.

    ItrCOs a lot smaller download than Autodesk Maya or proprietary
    alternatives like that.

    Anyway, matter not in a sense. Its a tool. And it fun to program in
    Python for it.

    I would say it caters to both sides of the brain -- artistic and
    technical. Skill in CG depends on a lot on developing capacity in
    both.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From BGB@cr88192@gmail.com to comp.lang.c on Thu Aug 13 23:07:01 2026
    From Newsgroup: comp.lang.c

    On 8/13/2026 4:36 PM, Chris M. Thomasson wrote:
    On 8/13/2026 2:37 AM, BGB wrote:
    [...]

    Fwiw, I made this in OpenSCAD, its pretty nice. openscad Almost reminds
    me of povray...

    https://skfb.ly/oqQEV



    Similar syntax, as can be noted.


    A few limitations I have found, but still deciding on a strategy
    (whether to extend the language for my own uses, or make/use a different
    one that does the same basic thing but addresses a few of the
    weak-points; hopefully without creating new ones); or do nothing, and
    stick with the existing language as-is.

    Mostly works OK for both making parts to 3D print and also making basic
    3D models.

    Gives a lot of control and ability to edit things, but does depend some
    on thinking and mental math at times.


    As noted, in any case, I am not a fan of external dependencies, and particularly not large external dependencies.


    So, a "new" viewer, if implemented, would probably be a fairly simple
    program to do the CSG and display the result. May or may not have a
    built-in text editor, the other main option being to have a hot-reload key.

    May make sense to keep it backwards compatible with SCAD though, which
    leans more towards a modified superset rather than an entirely new language.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From BGB@cr88192@gmail.com to comp.lang.c on Thu Aug 13 23:47:27 2026
    From Newsgroup: comp.lang.c

    On 8/13/2026 9:41 PM, Lawrence DrCOOliveiro wrote:
    On Thu, 13 Aug 2026 18:50:05 -0700, Chris M. Thomasson wrote:

    Blender is pretty nice. But, its a bit large.

    ItrCOs a lot smaller download than Autodesk Maya or proprietary
    alternatives like that.


    Better not to poke those with a stick IMO.

    They are specially designed to try to create vendor lock-in and then
    trick people into paying subscriptions to keep using the software; not
    worth it.


    Anyway, matter not in a sense. Its a tool. And it fun to program in
    Python for it.

    I would say it caters to both sides of the brain -- artistic and
    technical. Skill in CG depends on a lot on developing capacity in
    both.

    Yes, but still doesn't mean one wants to create a hard dependency on
    Blender or Python...


    Like, if you want a shovel...

    It doesn't matter that a Backhoe is smaller and cheaper than an Excavator.

    ...


    Sometimes, one just wants a few tools:
    A tool that converts a language to a 3D model in a specified format via
    a command-like or text-script so that it can be packaged up in some
    asset format (or output geometry as STL or "Wavefront OBJ" or similar);
    Another tool that allows viewing the 3D model, and launches quickly and doesn't require dealing with some cumbersome file selector dialog and
    import UI and similar;
    ...


    Like, you might just want to be like:
    Make tool;
    Associate file extension with tool;
    Double click;
    Done, view file;
    Close program when done looking at model, or have a reload hot-key for
    when one wants to edit the file (via something like Notepad).


    Or, say, like "Windows Photo Viewer" vs GIMP. Even if both have "open a
    photo and look at it" as features, they are still not really the same
    thing. Both serve very different roles in terms of purpose and UX.

    Or, by extension, "Microsoft 3D Viewer" vs Blender.
    3D Viewer likely being a closer analogy, but more obscure.


    And, no big central "do everything" programs needed or desired in many cases...

    Doesn't mean the big central program can't have it as well, but assuming
    the big central program is the end-all be-all, is seriously missing the
    point.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From BGB@cr88192@gmail.com to comp.lang.c on Thu Aug 13 23:50:16 2026
    From Newsgroup: comp.lang.c

    On 8/11/2026 3:47 PM, Chris M. Thomasson wrote:
    On 8/11/2026 8:17 AM, James Kuyper wrote:
    On 2026-08-10 21:44, BGB wrote:
    On 8/10/2026 7:03 PM, James Kuyper wrote:
    On 2026-08-10 18:31, BGB wrote:
    Snipped section included my epic fail at trying to use traditional >>>> style
    mathematical notation in a Usenet post...

    It was bugging me, by implying the conjugate was a scalar, where
    no, the
    conjugate is not a scalar...

    I'm not sure what you're saying. As far as C is concerned. complex
    types
    are floating types (6.2.5p15), and therefore arithmetic types
    (6.2.5p23), and therefore scalar types (6.2.5p26) Therefore, a function >>>> that returns the conjugate of its argument would return a scalar type.

    I wrote:
    -a-a-a R^-1 = (R.r-R.i-R.j-R.k) / (R.r*R.r + R.i*R.i + R.j*R.j + R.k*R.k) >>>
    The problem:
    -a-a-a (R.r-R.i-R.j-R.k)
    Should have been, say:
    -a-a-a (R.r - R.i*I - R.j*J - R.k*K)

    Which was bugging me, because either the former would be interpreted as
    meaning a scalar (or real-valued) result, or "R.i*R.i" as being
    negative, neither of which was true in the intended expression...

    I was confused because you were writing about complex numbers, mentioned
    that you had snipped some material, and then made a comment that I
    assumed, from context, was also about complex numbers. I did not realize
    that there was a context switch to quaternions inside the snipped
    material.
    In the unlikely event that that were added to C, quaternions would
    almost certainly be added as a new arithmetic (and therefore, scalar)
    type, by analogy with the complex types. I was unaware, until just now
    when I looked it up, that the real part of a quaternion is often
    referred to as it's scalar part.
    That's a little odd, because I'm one of the probably very few people
    here who've actually made practical use of quaternions. I had to deal
    with data about spacecraft orientation that was stored as a quaternion,
    and convert between quaternions and corresponding Euler angles and
    Rotation matrices. However, a quaternion library was part of the
    standard toolkit for that project, which makes sense.

    quaternion are very useful for such things. Avoiding gimbal lock?

    Among other things:
    No gimbal lock;
    Can LERP/SLERP;
    SLERP'ing between identity and a given rotation allows scaling the rotation; Can be used as a vector for angular velocity or angular inertia math;
    Can be multiplied for compound rotations (like with matrix math);

    Try to SLERP a matrix, and it may "rubber band" or have other weird
    glitches;
    Try to LERP Euler angles and the motion may end up going in some totally
    weird direction;
    ...

    If you use two of them (a "dual quaternion"), it is possible to express
    fairly arbitrary transforms (translation + rotation).

    Like, were pretty useful for doing something like a rigid-body physics
    engine, even if the physics engine itself turned out to not be very useful.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Fri Aug 14 04:59:19 2026
    From Newsgroup: comp.lang.c

    On Thu, 13 Aug 2026 23:47:27 -0500, BGB wrote:

    On 8/13/2026 9:41 PM, Lawrence DrCOOliveiro wrote:

    On Thu, 13 Aug 2026 18:50:05 -0700, Chris M. Thomasson wrote:

    Blender is pretty nice. But, its a bit large.

    ItrCOs a lot smaller download than Autodesk Maya or proprietary
    alternatives like that.

    Better not to poke those with a stick IMO.

    They are specially designed to try to create vendor lock-in and then
    trick people into paying subscriptions to keep using the software;
    not worth it.

    TheyrCOre also specialist tools. TheyrCOve given up being a complete
    workflow solution. So you need to spend even more money buying even
    more tools to get work done.

    No, they are not in a position to compete with open-source tools. All
    theyrCOve got is a multi-million-dollar publicity budget to tell
    everyone how wonderful they are. So they cater to those who are
    willing to swallow such things, and thatrCOs enough to make them even
    more rich. They donrCOt need any more.

    Anyway, matter not in a sense. Its a tool. And it fun to program in
    Python for it.

    I would say it caters to both sides of the brain -- artistic and
    technical. Skill in CG depends on a lot on developing capacity in
    both.

    Yes, but still doesn't mean one wants to create a hard dependency on
    Blender or Python...

    The open-source world makes heavy use of code reuse. ThatrCOs why itrCOs
    such a productive place to be.

    YourCOre still thinking in Windows terms, arenrCOt you? Where everything
    has to be downloaded individually and installed manually, there is no integrated package manager to deal with the details for you.

    Sometimes, one just wants a few tools:
    A tool that converts a language to a 3D model in a specified format
    via a command-like or text-script so that it can be packaged up in
    some asset format (or output geometry as STL or "Wavefront OBJ" or
    similar); Another tool that allows viewing the 3D model, and
    launches quickly and doesn't require dealing with some cumbersome
    file selector dialog and import UI and similar; ...

    All doable.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Fri Aug 14 05:59:39 2026
    From Newsgroup: comp.lang.c

    On Thu, 13 Aug 2026 23:50:16 -0500, BGB wrote:

    SLERP'ing between identity and a given rotation allows scaling the
    rotation;

    You canrCOt linearly interpolate the sines and cosines, though. If you
    want to do linear interpolation of the rotation angle, donrCOt you have
    to compute inverse sines/cosines, calculate new angles and then back
    again?
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From BGB@cr88192@gmail.com to comp.lang.c on Fri Aug 14 03:16:02 2026
    From Newsgroup: comp.lang.c

    On 8/14/2026 12:59 AM, Lawrence DrCOOliveiro wrote:
    On Thu, 13 Aug 2026 23:50:16 -0500, BGB wrote:

    SLERP'ing between identity and a given rotation allows scaling the
    rotation;

    You canrCOt linearly interpolate the sines and cosines, though. If you
    want to do linear interpolation of the rotation angle, donrCOt you have
    to compute inverse sines/cosines, calculate new angles and then back
    again?

    This is where it can get funny:
    While naive interpolation goes off the unit-sphere, re-normalizing the quaternion generally puts it back at around the position it would have
    been had one followed an arc over the surface of the hyper-sphere
    between these points (at least within +/- 180 degrees, and not
    necessarily at a uniform velocity if the distance is large).

    This is both more convenient and cheaper than using sines or cosines or
    trying to follow an arc. One can use them, but don't need to.

    More accuracy (and more uniform speed) is possible with a normalized
    LERP though by using a subdivision trick similar to that used for
    matrices if the points are further apart, though in this case it is a
    little cheaper, say:
    qnlerp(A,B,f)
    if(qdist2(A,B)<CUTOFF)
    return qnormalize(A*(1-f)+(B+f));
    C=qnormalize((A+B)*0.5);
    if(frac<0.5)
    return qnlerp(A,C,f*2);
    return qnlerp(C,B,f*2-1);


    Though, they still come up if moving to/from axis/angle or similar.

    As can be noted, multiplying rotations also effectively concatenates them.

    Can't really explain how it works...

    Granted, there are some weird cases that need to be worked around, but
    mostly it all "just sorta works"...


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Fri Aug 14 08:32:55 2026
    From Newsgroup: comp.lang.c

    On Fri, 14 Aug 2026 03:16:02 -0500, BGB wrote:

    On 8/14/2026 12:59 AM, Lawrence DrCOOliveiro wrote:

    On Thu, 13 Aug 2026 23:50:16 -0500, BGB wrote:

    SLERP'ing between identity and a given rotation allows scaling the
    rotation;

    You canrCOt linearly interpolate the sines and cosines, though. If
    you want to do linear interpolation of the rotation angle, donrCOt
    you have to compute inverse sines/cosines, calculate new angles and
    then back again?

    This is where it can get funny:
    While naive interpolation goes off the unit-sphere, re-normalizing
    the quaternion generally puts it back at around the position it
    would have been had one followed an arc over the surface of the
    hyper-sphere between these points (at least within +/- 180 degrees,
    and not necessarily at a uniform velocity if the distance is large).

    This is both more convenient and cheaper than using sines or cosines
    or trying to follow an arc. One can use them, but don't need to.

    Ha! Thanks for that.

    I was thinking in terms of inverting the formula for the quaternion
    for double the angle to get the one for half the angle. Probably
    involve square roots, which is still less computation than trig.

    After our previous exchange on quaternions, I was doing some
    experiments in Blender to see if I could patch up near-full-circle
    rotations in the wrong direction just by fiddling the quaternions, not
    by adding more key frames. Negating the W (cosine) component does flip
    the rotation direction, but the in-between rotation rate can go a bit
    wild unless you tweak one or two of the other components (i.e.
    contributions to the sine component) as well.

    As can be noted, multiplying rotations also effectively concatenates
    them.

    Can't really explain how it works...

    First of all, a quaternion consists of a vector (X, Y, Z) and scalar
    (W) part. The direction of the vector part gives the rotation axis,
    while its magnitude gives the sine of the half angle. The scalar part
    is the cosine of the half angle.

    Applying a rotation to a vector involves multiplying the quaternion by
    the vector. If this is just a special case of rotating a quaternion
    (i.e. nonzero scalar part), then it probably follows from that ...
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c on Fri Aug 14 12:17:54 2026
    From Newsgroup: comp.lang.c

    On 8/13/2026 9:50 PM, BGB wrote:
    On 8/11/2026 3:47 PM, Chris M. Thomasson wrote:
    On 8/11/2026 8:17 AM, James Kuyper wrote:
    On 2026-08-10 21:44, BGB wrote:
    On 8/10/2026 7:03 PM, James Kuyper wrote:
    On 2026-08-10 18:31, BGB wrote:
    Snipped section included my epic fail at trying to use
    traditional
    style
    mathematical notation in a Usenet post...

    It was bugging me, by implying the conjugate was a scalar, where
    no, the
    conjugate is not a scalar...

    I'm not sure what you're saying. As far as C is concerned. complex
    types
    are floating types (6.2.5p15), and therefore arithmetic types
    (6.2.5p23), and therefore scalar types (6.2.5p26) Therefore, a
    function
    that returns the conjugate of its argument would return a scalar type. >>>>
    I wrote:
    -a-a-a R^-1 = (R.r-R.i-R.j-R.k) / (R.r*R.r + R.i*R.i + R.j*R.j + R.k*R.k) >>>>
    The problem:
    -a-a-a (R.r-R.i-R.j-R.k)
    Should have been, say:
    -a-a-a (R.r - R.i*I - R.j*J - R.k*K)

    Which was bugging me, because either the former would be interpreted as >>>> meaning a scalar (or real-valued) result, or "R.i*R.i" as being
    negative, neither of which was true in the intended expression...

    I was confused because you were writing about complex numbers, mentioned >>> that you had snipped some material, and then made a comment that I
    assumed, from context, was also about complex numbers. I did not realize >>> that there was a context switch to quaternions inside the snipped
    material.
    In the unlikely event that that were added to C, quaternions would
    almost certainly be added as a new arithmetic (and therefore, scalar)
    type, by analogy with the complex types. I was unaware, until just now
    when I looked it up, that the real part of a quaternion is often
    referred to as it's scalar part.
    That's a little odd, because I'm one of the probably very few people
    here who've actually made practical use of quaternions. I had to deal
    with data about spacecraft orientation that was stored as a quaternion,
    and convert between quaternions and corresponding Euler angles and
    Rotation matrices. However, a quaternion library was part of the
    standard toolkit for that project, which makes sense.

    quaternion are very useful for such things. Avoiding gimbal lock?

    Among other things:
    No gimbal lock;
    Can LERP/SLERP;
    SLERP'ing between identity and a given rotation allows scaling the
    rotation;
    Can be used as a vector for angular velocity or angular inertia math;
    Can be multiplied for compound rotations (like with matrix math);

    Try to SLERP a matrix, and it may "rubber band" or have other weird glitches;
    Try to LERP Euler angles and the motion may end up going in some totally weird direction;
    ...

    If you use two of them (a "dual quaternion"), it is possible to express fairly arbitrary transforms (translation + rotation).

    Like, were pretty useful for doing something like a rigid-body physics engine, even if the physics engine itself turned out to not be very useful.



    Its interesting. Fwiw, I can get all of the bone matrices to work in my shaders without using quaternion. But, that just the way I coded it up.
    List animations, play them, etc. In my experimental engine. Have you
    taken a look at the assimp lib yet? Oh its helps!

    Iirc, GLM has a glm::quat... :^)

    Note it, read it, want it... ;^D

    https://github.com/g-truc/glm
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c on Fri Aug 14 12:36:25 2026
    From Newsgroup: comp.lang.c

    On 8/13/2026 10:59 PM, Lawrence DrCOOliveiro wrote:
    On Thu, 13 Aug 2026 23:50:16 -0500, BGB wrote:

    SLERP'ing between identity and a given rotation allows scaling the
    rotation;

    You canrCOt linearly interpolate the sines and cosines, though. If you
    want to do linear interpolation of the rotation angle, donrCOt you have
    to compute inverse sines/cosines, calculate new angles and then back
    again?

    To interpolate the rotation angle? Something simple, linear:

    // typed in the newsreader sorry for any typos

    ________________________
    unsigned long n = 42; // granularity and iter all in one...

    float angle_min = 0;
    float angle_max = PI/2;
    float angle_dif = angle_max - angle_min;

    float normal_base = 1.f/n

    for (unsigned long i = 0; i < n; ++i)
    {
    float normal = normal_base * i;
    float angle = angle_min + angle_dif * normal;

    float x0 = cos(angle);
    float y0 = sin(angle);

    // (x0, y0) as normalized here

    // render line from (0, 0) to (x0, y0)...
    }
    ________________________

    Now, this missed normal equaling 1 during iteration... We can do two
    things here if that is in your requirements. Alter the base, or over
    iterate by one. The prior needs to resist division by zero.

    float normal_base = (n > 1) ? 1.f/(n-1) : 0.f;
    for (unsigned long i = 0; i < n; ++i) { ... }


    vs...

    float normal_base = 1.f/n;
    for (unsigned long i = 0; i <= n; ++i) { ... }

    One of the methods over extend i such that i can equal n. Beware of that
    in case you are using i to index into an array or something...

    So, we need to ponder on the i-1 for the normal_base, or the over
    iterate if we want normal in the loop to reach angle_max. Fair enough?

    ;^)
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Sat Aug 15 03:16:38 2026
    From Newsgroup: comp.lang.c

    On Fri, 14 Aug 2026 12:36:25 -0700, Chris M. Thomasson wrote:

    float angle_min = 0;
    float angle_max = PI/2;
    float angle_dif = angle_max - angle_min;

    float normal_base = 1.f/n

    for (unsigned long i = 0; i < n; ++i)
    {
    float normal = normal_base * i;
    float angle = angle_min + angle_dif * normal;

    float x0 = cos(angle);
    float y0 = sin(angle);

    // (x0, y0) as normalized here

    // render line from (0, 0) to (x0, y0)...
    }

    But the quaternion doesnrCOt directly give you the angle to begin with,
    you will need to do an inverse trig computation to get it. And then do
    the above trig calls for every segment.

    I just wondered if there was a way to go straight from cos/sin of an
    angle to cos/sin of fractions of that angle ... I think there is.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c on Fri Aug 14 22:38:37 2026
    From Newsgroup: comp.lang.c

    On 8/14/2026 8:16 PM, Lawrence DrCOOliveiro wrote:
    On Fri, 14 Aug 2026 12:36:25 -0700, Chris M. Thomasson wrote:

    float angle_min = 0;
    float angle_max = PI/2;
    float angle_dif = angle_max - angle_min;

    float normal_base = 1.f/n

    for (unsigned long i = 0; i < n; ++i)
    {
    float normal = normal_base * i;
    float angle = angle_min + angle_dif * normal;

    float x0 = cos(angle);
    float y0 = sin(angle);

    // (x0, y0) as normalized here

    // render line from (0, 0) to (x0, y0)...
    }

    But the quaternion doesnrCOt directly give you the angle to begin with,
    you will need to do an inverse trig computation to get it. And then do
    the above trig calls for every segment.

    Or start from the angles and create a quat?


    I just wondered if there was a way to go straight from cos/sin of an
    angle to cos/sin of fractions of that angle ... I think there is.

    Depends on what angles you are looking for?

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Sun Aug 16 00:08:27 2026
    From Newsgroup: comp.lang.c

    On Fri, 14 Aug 2026 22:38:37 -0700, Chris M. Thomasson wrote:

    Or start from the angles and create a quat?

    You mean, carry the angle around as a separate quantity, in addition
    to the quaternion representing i?

    Depends on what angles you are looking for?

    The angle represented by the quaternion.
    --- Synchronet 3.22a-Linux NewsLink 1.2