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?
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.
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?
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.
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.
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.
On Sun, 02 Aug 2026 14:17:45 +0000, Kenny McCormack wrote:[snip]
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().
[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.
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" ?
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.
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.
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.
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?
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.
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!
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.
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.
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?
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. ;^)
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.
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.
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.
| Sysop: | Tetrazocine |
|---|---|
| Location: | Melbourne, VIC, Australia |
| Users: | 12 |
| Nodes: | 8 (0 / 8) |
| Uptime: | 201:38:43 |
| Calls: | 220 |
| Files: | 21,513 |
| Messages: | 83,420 |