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-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.
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.
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.
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.
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.-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.
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!
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.
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.)
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.
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.-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. ;^)
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.
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.
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.
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
Then often u16/u32/u64, s16/s32/s64, ...Its been a while since I used c99 on windows, but iirc, their (MSVC)
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).
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.
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.
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 :-)
On Mon, 03 Aug 2026 14:47:21 +0000, Lew Pitcher wrote:
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.
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 <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:[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.
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.
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:[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.
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.
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.
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.
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 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.
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 ..."
fwiw, I personally prefer unsigned char for all of my raw buffers
and such, but that's just me.
... (though last I checked, MSVC still doesn't fully support C99;
eg, still no VLAs or _Complex).
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).
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 ...
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.
Then often u16/u32/u64, s16/s32/s64, ...Its been a while since I used c99 on windows, but iirc, their (MSVC)
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).
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.
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.
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).
...
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
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.
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.
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 ...
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 ...
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.
Well, until what point I end up needing to move off Win10, then
probably over to Linux or something at this point.
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?
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.
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?
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.
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).
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.
IMHO it would be cleaner to require plain char to be unsigned,
but I don't see that happening.
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.
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.
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.
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.
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.
I don't write like an A.I.-a Nor L.L.M.
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!
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.
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.
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.
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.
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.
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.
If I need to move off of Win10, will probably just go over to Debian
or something...
I am admittedly skeptical of the whole "AI PC" thing ...
... likewise for people trying to now sell "PCs" based on repurposed cellphone parts.
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).
Would also be nice to have fully unlocked software though.
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.
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.
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`).
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.
[...]
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.
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.
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.)
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.
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)
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.
[...]
[...]
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.
[..]
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:Ah, right you are. `isascii` was marked obsolescent in POSIX
[...]
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.
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.
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.
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?
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.
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:Ah, right you are. `isascii` was marked obsolescent in POSIX
[...]
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.
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?
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?
[**] 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
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,)
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.)
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.
In contrast, Complex is relatively little used in my use-cases. Most
signal processing tasks I do are real-valued;
Yeah, complex is rarely all that useful.[...]
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?
Now, why doesn't C support the triplex numbers?
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.
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.
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.
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:Of course.-a As I said, /few/ programmers does not mean /no/
[...]
Yeah, complex is rarely all that useful.[...]
For me personally, its very useful. But, well, that's just me.
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).
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:Of course.-a As I said, /few/ programmers does not mean /no/
[...]
Yeah, complex is rarely all that useful.[...]
For me personally, its very useful. But, well, that's just me.
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.)
Snipped section included my epic fail at trying to use traditional
style mathematical notation in a Usenet post...
Snipped section included my epic fail at trying to use traditionalstyle
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...
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).
On 2026-08-10 18:31, BGB wrote:
Snipped section included my epic fail at trying to use traditionalstyle
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.
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).
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).
...
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.
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).
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).
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.
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.
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?
On 2026-08-10 18:31, BGB wrote:
Snipped section included my epic fail at trying to use traditionalstyle
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.
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 traditionalstyle
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...
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 traditionalstyle
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.
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 traditionalstyle
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.
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 traditionalstyle
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.
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, ....
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.
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.
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).
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.
Say, if lerping between two points that are nearly 360 degrees
apart, then, the interpolation will tend to perform an unexpected full-rotation.
I have found I would rather not use point-and-click tools for 3D
modeling (weird, I know).
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.
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
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...
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.
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
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.
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.
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).
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/>.
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...
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.
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.
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
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.
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?
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...
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; ...
SLERP'ing between identity and a given rotation allows scaling the
rotation;
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?
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.
As can be noted, multiplying rotations also effectively concatenates
them.
Can't really explain how it works...
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:I wrote:
Snipped section included my epic fail at trying to usetraditional
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. >>>>
-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.
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?
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)...
}
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.
Or start from the angles and create a quat?
Depends on what angles you are looking for?
| Sysop: | Amessyroom |
|---|---|
| Location: | Fayetteville, NC |
| Users: | 74 |
| Nodes: | 6 (0 / 6) |
| Uptime: | 47:46:14 |
| Calls: | 1,100 |
| Files: | 1,339 |
| Messages: | 275,630 |