• Default signedness of 'plain' char.

    From Kenny McCormack@3:633/10 to All on Sun Aug 2 14:17:45 2026
    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?

    --
    Treating the stock market indexes as general measures of the well-being of a society is like treating your blood pressure as an indicator of health. The higher, the better, right? In fact, a high stock market is good for the investor
    class, but it means the rest of us are getting screwed better than ever.

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Johann 'Myrkraverk' Oskarsson@3:633/10 to All on Mon Aug 3 02:45:01 2026
    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

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Kenny McCormack@3:633/10 to All on Mon Aug 3 01:47:09 2026
    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!"


    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From David Brown@3:633/10 to All on Mon Aug 3 09:56:49 2026
    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.





    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Waldek Hebisch@3:633/10 to All on Mon Aug 3 13:48:59 2026
    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

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Dan Cross@3:633/10 to All on Mon Aug 3 14:47:23 2026
    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
    |e?cient 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
    |de?ned to be _how the target machine?s 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 e?cient 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 speci?ed: 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.


    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Lew Pitcher@3:633/10 to All on Mon Aug 3 14:47:21 2026
    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.

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Lew Pitcher@3:633/10 to All on Mon Aug 3 15:04:38 2026
    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.

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Johann 'Myrkraverk' Oskarsson@3:633/10 to All on Mon Aug 3 23:14:53 2026
    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

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From bart@3:633/10 to All on Mon Aug 3 17:04:31 2026
    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˙ <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.

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

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

    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.



    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Johann 'Myrkraverk' Oskarsson@3:633/10 to All on Tue Aug 4 00:23:11 2026
    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˙ <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.

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

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

    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

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From bart@3:633/10 to All on Mon Aug 3 18:03:51 2026
    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.˙ 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.

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

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Johann 'Myrkraverk' Oskarsson@3:633/10 to All on Tue Aug 4 01:26:44 2026
    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.˙ 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.

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

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From BGB@3:633/10 to All on Mon Aug 3 13:56:57 2026
    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.˙ 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.)


    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)
    {
    ˙˙˙˙ 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.






    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Chris M. Thomasson@3:633/10 to All on Mon Aug 3 13:20:07 2026
    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.

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From bart@3:633/10 to All on Mon Aug 3 22:06:38 2026
    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.˙ 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. ;^)

    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.



    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Chris M. Thomasson@3:633/10 to All on Mon Aug 3 14:25:06 2026
    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.˙ 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. ;^)

    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.

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From BGB@3:633/10 to All on Mon Aug 3 18:38:03 2026
    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.˙ 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. ;^)

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

    ...



    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Keith Thompson@3:633/10 to All on Mon Aug 3 16:58:39 2026
    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 */

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)