40 are flagged as outliers. Up to 40, no problem. Random numbersdataset of any size: no problem.
Wrote a C program to mimic the stats shown on:
https://www.calculatorsoup.com/calculators/statistics/descriptivestatistics.php
My code compiles and works fine - every stat matches - except for one >anomaly: when using a dataset of consecutive numbers 1 to N, all values
40 are flagged as outliers. Up to 40, no problem. Random numbersdataset of any size: no problem.
And values 41+ definitely don't meet the conditions for outliers (using
the IQR * 1.5 rule).
Very strange.
Edit: I just noticed I didn't initialize a char:
before: char outliers[100];
after : char outliers[100] = "";
And the problem went away. Reset it to before and problem came back.
Makes no sense. What could cause the program to go FUBAR at data point
41+ only when the dataset is consecutive numbers?
Also, why doesn't gcc just do you a solid and initialize to "" for you?
Wrote a C program to mimic the stats shown on:
https://www.calculatorsoup.com/calculators/statistics/descriptivestatistics.php
My code compiles and works fine - every stat matches - except for one anomaly: when using a dataset of consecutive numbers 1 to N, all values
40 are flagged as outliers. Up to 40, no problem. Random numbersdataset of any size: no problem.
And values 41+ definitely don't meet the conditions for outliers (using
the IQR * 1.5 rule).
Very strange.
Edit: I just noticed I didn't initialize a char:
before: char outliers[100];
after : char outliers[100] = "";
And the problem went away. Reset it to before and problem came back.
Makes no sense. What could cause the program to go FUBAR at data point
41+ only when the dataset is consecutive numbers?
Also, why doesn't gcc just do you a solid and initialize to "" for you?
Wrote a C program to mimic the stats shown on:
https://www.calculatorsoup.com/calculators/statistics/descriptivestatistics.php
My code compiles and works fine - every stat matches - except for one anomaly: when using a dataset of consecutive numbers 1 to N, all values
40 are flagged as outliers. Up to 40, no problem. Random numbersdataset of any size: no problem.
And values 41+ definitely don't meet the conditions for outliers (using
the IQR * 1.5 rule).
Very strange.
Edit: I just noticed I didn't initialize a char:
before: char outliers[100];
after : char outliers[100] = "";
And the problem went away. Reset it to before and problem came back.
Makes no sense. What could cause the program to go FUBAR at data point
41+ only when the dataset is consecutive numbers?
Also, why doesn't gcc just do you a solid and initialize to "" for you?
On Wed, 12 Jun 2024 16:47:23 -0400, DFS <[email protected]> wrote:
Wrote a C program to mimic the stats shown on:
https://www.calculatorsoup.com/calculators/statistics/descriptivestatistics.php
My code compiles and works fine - every stat matches - except for one
anomaly: when using a dataset of consecutive numbers 1 to N, all values
40 are flagged as outliers. Up to 40, no problem. Random numbersdataset of any size: no problem.
And values 41+ definitely don't meet the conditions for outliers (using
the IQR * 1.5 rule).
Very strange.
Edit: I just noticed I didn't initialize a char:
before: char outliers[100];
after : char outliers[100] = "";
And the problem went away. Reset it to before and problem came back.
Makes no sense. What could cause the program to go FUBAR at data point
41+ only when the dataset is consecutive numbers?
Also, why doesn't gcc just do you a solid and initialize to "" for you?
Makes perfect sense. The first rule of undefined behavior is
"Whatever happens is exactly correct." You are not entitled to any expectations and none of the behavior (or perhaps all of the behavior)
can be called unexpected.
Since we cannot see your code, I will guess that you use a non-zero
value in outliers[i] to indicate that the corresponding value has been identified as an outlier.
Since you did not initialize the array
outliers, you have no idea what indeterminate value any element of the
array contains when your program begins execution. Apparently some of
them are non-zero. The fact that the first 40 are zero and the
remaining non-zero is merely an artifact of how your system builds
this particular program with that particular set of compile and link
options. Change anything and you could see completely different
behavior, or not.
I don't use gcc but, in debug mode, some compilers will put
recognizable "garbage values" in uninitialized variables so you can
spot the condition more easily.
In any case, the C language does not prevent you from shooting
yourself in the foot if you choose to. Evaluating an indeterminate
value is one fairly common way to do this.
Janis Papanagnou <[email protected]> writes:
On 12.06.2024 22:47, DFS wrote:[...]
[...]before: char outliers[100];
after : char outliers[100] = "";
Seriously; why do you expect [in C] a declaration to initialize that
stack object? (There are other languages that do initializations as
the language defines it, but C doesn't; it may help to learn before
programming in any language?) And why do you think that "" would be
an appropriate initialization (i.e. a single '\0' character) and not
all 100 elements set to '\0'? (Someone else might want to access the
element 'answer[99]'.) And should we pay for initializing 1000000000
characters in case one declares an appropriate huge array?
This:
char outliers[100] = "";
initializes all 100 elements to zero. So does this:
char outliers[100] = { '\0' };
Any elements or members not specified in an initializer are set to zero.
If you want to set an array's 0th element to 0 and not waste time initializing the rest, you can assign it separately:
char outliers[100];
outliers[0] = '\0';
or
char outliers[100];
strcpy(outliers, "");
though the overhead of the function call is likely to outweigh the
cost of initializing the array.
DFS <[email protected]> writes:
On 6/12/2024 5:30 PM, Barry Schwarz wrote:
On Wed, 12 Jun 2024 16:47:23 -0400, DFS <[email protected]> wrote:
Wrote a C program to mimic the stats shown on:
https://www.calculatorsoup.com/calculators/statistics/descriptivestatistics.php
My code compiles and works fine - every stat matches - except for one
anomaly: when using a dataset of consecutive numbers 1 to N, all values >>>>> 40 are flagged as outliers. Up to 40, no problem. Random numbers
dataset of any size: no problem.
And values 41+ definitely don't meet the conditions for outliers (using >>>> the IQR * 1.5 rule).
Very strange.
Edit: I just noticed I didn't initialize a char:
before: char outliers[100];
after : char outliers[100] = "";
And the problem went away. Reset it to before and problem came back.
Makes no sense. What could cause the program to go FUBAR at data point >>>> 41+ only when the dataset is consecutive numbers?
Also, why doesn't gcc just do you a solid and initialize to "" for you? >>> Makes perfect sense. The first rule of undefined behavior is"Whatever happens is exactly correct." You are not entitled to any
expectations and none of the behavior (or perhaps all of the behavior)
can be called unexpected.
I HATE bogus answers like this.
Aren't you embarrassed to say things like that?
He has nothing to be embarrassed about. What he wrote is correct.
The C standard's definition of "undefined behavior" is "behavior, upon
use of a nonportable or erroneous program construct or of erroneous
data, for which this International Standard imposes no requirements".
If you don't like the way C deals with undefined behavior, that's
perfectly valid, and a lot of people are likely to agree with you.
But I advise against lashing out at people who are correctly explaining
what the C standard says.
DFS, since you've been posting in comp.lang.c for at least ten years,
I'm surprised you're having difficulties with this.
On 12/06/2024 22:47, DFS wrote:
Wrote a C program to mimic the stats shown on:
https://www.calculatorsoup.com/calculators/statistics/descriptivestatistics.php
My code compiles and works fine - every stat matches - except for one
anomaly: when using a dataset of consecutive numbers 1 to N, all
values > 40 are flagged as outliers. Up to 40, no problem. Random
numbers dataset of any size: no problem.
And values 41+ definitely don't meet the conditions for outliers
(using the IQR * 1.5 rule).
Very strange.
Edit: I just noticed I didn't initialize a char:
before: char outliers[100];
after : char outliers[100] = "";
And the problem went away. Reset it to before and problem came back.
Makes no sense. What could cause the program to go FUBAR at data
point 41+ only when the dataset is consecutive numbers?
Also, why doesn't gcc just do you a solid and initialize to "" for you?
It is /really/ difficult to know exactly what your problem is without
seeing your C code! There may be other problems that you haven't seen yet.
Non-static local variables without initialisers have "indeterminate"
value if there is no initialiser. Trying to use these "indeterminate" values is undefined behaviour - you have absolutely no control over what might happen. Any particular behaviour you see is done to luck from the rest of the code and what happened to be in memory at the time.
There is no automatic initialisation of non-static local variables,
because that would often be inefficient.
The best way to avoid errors
like yours, IMHO, is not to declare such variables until you have data
to put in them - thus you always have a sensible initialiser of real
data. Occasionally that is not practical, but it works in most cases.
For a data array, zero initialisation is common. Typically you do this
with :
int xs[100] = { 0 };
That puts the explicit 0 in the first element of xs, and then the rest
of the array is cleared with zeros.
I recommend never using "char" as a type unless you really mean a > character, limited to 7-bit ASCII. So if your "outliers" array really
is an array of such characters, "char" is fine. If it is intended to be numbers and for some reason you specifically want 8-bit values, use
"uint8_t" or "int8_t", and initialise with { 0 }.
A major lesson here is to learn how to use your tools. C is not a
forgiving language. Make use of all the help your tools can give you - enable warnings here. "gcc -Wall" enables a range of common warnings
with few false positives in normal well-written code, including ones
that check for attempts to read uninitialised data.
slew of extra warnings. Some of these will annoy people and trigger on
code they find reasonable, while most are good choices for a lot of code
- but personal preference varies significantly. And remember to enable optimisation, since it makes the static checking more powerful.
If you /really/ want gcc to zero out such local data automatically, use "-ftrivial-auto-var-init=zero". But it is much better to use warnings
and write correct code - options like that one are an addition to well-checked code for paranoid software in security-critical contexts.
This:
char outliers[100] = "";
initializes all 100 elements to zero. So does this:
char outliers[100] = { '\0' };
Any elements or members not specified in an initializer are set to zero.
If you want to set an array's 0th element to 0 and not waste time initializing the rest, you can assign it separately:
char outliers[100];
outliers[0] = '\0';
or
char outliers[100];
strcpy(outliers, "");
though the overhead of the function call is likely to outweigh the
cost of initializing the array.
//no outliers
if ( min > lo && max < hi) {
strcat(outliers,"none (using IQR * 1.5 rule)");
}
//at least one outlier
if ( min < lo || max > hi) {
for(i = 0; i < N; i++) {
double val = (double)nums[i];
if(val < lo || val > hi) {
sprintf(temp,"%.0f ",val);
temp[strlen(temp)] = '\0';
strcat(outliers,temp);
}
}
strcat(outliers," (using IQR * 1.5 rule)");
}
Wrote a C program to mimic the stats shown on:
https://www.calculatorsoup.com/calculators/statistics/descriptivestatistics.php
My code compiles and works fine - every stat matches - except for one anomaly: when using a dataset of consecutive numbers 1 to N, all values
40 are flagged as outliers. Up to 40, no problem. Random numbersdataset of any size: no problem.
And values 41+ definitely don't meet the conditions for outliers (using
the IQR * 1.5 rule).
Very strange.
Edit: I just noticed I didn't initialize a char:
before: char outliers[100];
after : char outliers[100] = "";
And the problem went away. Reset it to before and problem came back.
Makes no sense. What could cause the program to go FUBAR at data point
41+ only when the dataset is consecutive numbers?
Also, why doesn't gcc just do you a solid and initialize to "" for you?
David Brown <[email protected]> writes:
[...]
I recommend never using "char" as a type unless you really mean a[...]
character, limited to 7-bit ASCII. So if your "outliers" array really
is an array of such characters, "char" is fine. If it is intended to
be numbers and for some reason you specifically want 8-bit values, use
"uint8_t" or "int8_t", and initialise with { 0 }.
The implementation-definedness of plain char is awkward, but char
arrays generally work just fine for UTF-8 strings.
If char is
signed, byte values greater than 127 will be stored as negative
values, but it will almost certainly just work (if your system
is configured to handle UTF-8). Likewise for Latin-1 and similar
8-bit character sets.
The standard string functions operate on arrays of plain char, so
storing UTF-8 strings in arrays of uint8_t or unsigned char will
seriously restrict what you can do with them.
(I'd like to a future standard require plain char to be unsigned,
but I don't know how likely that is.)
On 13.06.2024 00:22, Keith Thompson wrote:
This:
char outliers[100] = "";
initializes all 100 elements to zero. So does this:
char outliers[100] = { '\0' };
Any elements or members not specified in an initializer are set to zero.
Oops! This surprised me. (But you are right.) The overhead isn't [syntactically] obvious, but I'm anyway always setting a single
'\0' character if I want to store strings in a 'char[]' and have
it initialized to an empty string (like below).
If you want to set an array's 0th element to 0 and not waste time
initializing the rest, you can assign it separately:
char outliers[100];
outliers[0] = '\0';
or
char outliers[100];
strcpy(outliers, "");
though the overhead of the function call is likely to outweigh the
cost of initializing the array.
It wouldn't occur to me to use the strcpy() function, but is the
function call really that expensive in C ?
On 6/12/2024 6:22 PM, Keith Thompson wrote:
Janis Papanagnou <[email protected]> writes:
On 12.06.2024 22:47, DFS wrote:[...]
[...]before: char outliers[100];
after : char outliers[100] = "";
Seriously; why do you expect [in C] a declaration to initialize that
stack object? (There are other languages that do initializations as
the language defines it, but C doesn't; it may help to learn before
programming in any language?) And why do you think that "" would be
an appropriate initialization (i.e. a single '\0' character) and not
all 100 elements set to '\0'? (Someone else might want to access the
element 'answer[99]'.) And should we pay for initializing 1000000000
characters in case one declares an appropriate huge array?
This:
char outliers[100] = "";
initializes all 100 elements to zero. So does this:
char outliers[100] = { '\0' };
Any elements or members not specified in an initializer are set to zero.
If you want to set an array's 0th element to 0 and not waste time
initializing the rest, you can assign it separately:
char outliers[100];
outliers[0] = '\0';
or
char outliers[100];
strcpy(outliers, "");
though the overhead of the function call is likely to outweigh the
cost of initializing the array.
Thanks. I'll have to remember these things. I like to use char arrays.
The problem is I don't use C very often, so I don't develop muscle memory.
On 6/12/2024 5:38 PM, David Brown wrote:
On 12/06/2024 22:47, DFS wrote:
Wrote a C program to mimic the stats shown on:
https://www.calculatorsoup.com/calculators/statistics/descriptivestatistics.php
My code compiles and works fine - every stat matches - except for one
anomaly: when using a dataset of consecutive numbers 1 to N, all
values > 40 are flagged as outliers. Up to 40, no problem. Random
numbers dataset of any size: no problem.
And values 41+ definitely don't meet the conditions for outliers
(using the IQR * 1.5 rule).
Very strange.
Edit: I just noticed I didn't initialize a char:
before: char outliers[100];
after : char outliers[100] = "";
And the problem went away. Reset it to before and problem came back.
Makes no sense. What could cause the program to go FUBAR at data
point 41+ only when the dataset is consecutive numbers?
Also, why doesn't gcc just do you a solid and initialize to "" for you?
It is /really/ difficult to know exactly what your problem is without
seeing your C code! There may be other problems that you haven't seen
yet.
The outlier section starts on line 169 =====================================================================================
Non-static local variables without initialisers have "indeterminate"
value if there is no initialiser. Trying to use these "indeterminate"
values is undefined behaviour - you have absolutely no control over
what might happen. Any particular behaviour you see is done to luck
from the rest of the code and what happened to be in memory at the time.
In 2024 that's surprising. I can't be the only one to forget to
initialize a char[] variable.
There is no automatic initialisation of non-static local variables,
because that would often be inefficient.
It would've saved me half an hour of frustration.
Now I'm getting 'stack smashing detected' errors (after the program runs correctly) when using datasets of consecutive numbers.
hmmmm 2 issues in a row using consecutives - that's a clue!
The best way to avoid errors like yours, IMHO, is not to declare such
variables until you have data to put in them - thus you always have a
sensible initialiser of real data. Occasionally that is not
practical, but it works in most cases.
Data is definitely going in them: either the value 'none' or a list of
the outliers and some text.
For a data array, zero initialisation is common. Typically you do
this with :
int xs[100] = { 0 };
That puts the explicit 0 in the first element of xs, and then the rest
of the array is cleared with zeros.
I recommend never using "char" as a type unless you really mean a >
character, limited to 7-bit ASCII. So if your "outliers" array really
is an array of such characters, "char" is fine. If it is intended to
be numbers and for some reason you specifically want 8-bit values, use
"uint8_t" or "int8_t", and initialise with { 0 }.
I did mean characters, limited to: 0-9a-zA-Z()
I think I'm using the char variable correctly.
sprintf(tempchar,"%d ",outlier);
strcat(char,tempchar);
A major lesson here is to learn how to use your tools. C is not a
forgiving language. Make use of all the help your tools can give you
- enable warnings here. "gcc -Wall" enables a range of common
warnings with few false positives in normal well-written code,
including ones that check for attempts to read uninitialised data.
I always use -Wall, and I was using it here.
"-Wextra" enables a
slew of extra warnings. Some of these will annoy people and trigger
on code they find reasonable, while most are good choices for a lot of
code - but personal preference varies significantly. And remember to
enable optimisation, since it makes the static checking more powerful.
Just did this:
gcc -Wall -Wextra -O3 mmv2.c -o mmv2 -lm
and no warnings or errors at all.
But: it now aborts near the front when using consecutive data points
(but not randoms).
*** buffer overflow detected ***: terminated
Aborted
I'm actually happy about that. I should be able to find and fix it.
If you /really/ want gcc to zero out such local data automatically,
use "-ftrivial-auto-var-init=zero". But it is much better to use
warnings and write correct code - options like that one are an
addition to well-checked code for paranoid software in
security-critical contexts.
Great answer! I can always count on D Brown for excellent advice.
Thank you.
On 2024-06-12, DFS <[email protected]> wrote:
//no outliers
if ( min > lo && max < hi) {
The condition for 'no outliers' is not the complement of
the condition for 'at least one outlier' below.
strcat(outliers,"none (using IQR * 1.5 rule)");
}
//at least one outlier
if ( min < lo || max > hi) {
for(i = 0; i < N; i++) {
double val = (double)nums[i];
if(val < lo || val > hi) {
sprintf(temp,"%.0f ",val);
temp[strlen(temp)] = '\0';
This is unnecessary;
sprintf terminates the generated string with a null character.
strcat(outliers,temp);
}
}
strcat(outliers," (using IQR * 1.5 rule)");
}
On 13/06/2024 00:34, DFS wrote:
On 6/12/2024 6:22 PM, Keith Thompson wrote:
Janis Papanagnou <[email protected]> writes:
On 12.06.2024 22:47, DFS wrote:[...]
[...]before: char outliers[100];
after : char outliers[100] = "";
Seriously; why do you expect [in C] a declaration to initialize that
stack object? (There are other languages that do initializations as
the language defines it, but C doesn't; it may help to learn before
programming in any language?) And why do you think that "" would be
an appropriate initialization (i.e. a single '\0' character) and not
all 100 elements set to '\0'? (Someone else might want to access the
element 'answer[99]'.) And should we pay for initializing 1000000000
characters in case one declares an appropriate huge array?
This:
char outliers[100] = "";
initializes all 100 elements to zero. So does this:
char outliers[100] = { '\0' };
Any elements or members not specified in an initializer are set to zero.
Yes. It's good to point that out, since people might assume that using
a string literal here only initialises the bit covered by that string literal.
(In C23 you can also write "char outliers[100] = {};" to get all zeros.)
If you want to set an array's 0th element to 0 and not waste time
initializing the rest, you can assign it separately:
char outliers[100];
outliers[0] = '\0';
or
char outliers[100];
strcpy(outliers, "");
though the overhead of the function call is likely to outweigh the
cost of initializing the array.
A good compiler will generate the same code for both cases - strcpy() is often inlined for such uses.
Thanks. I'll have to remember these things. I like to use char arrays. >>
The problem is I don't use C very often, so I don't develop muscle
memory.
What programming language do you usually use? And why are you writing
in C instead? (Or do you simply not do much programming?)
On 13/06/2024 01:33, Keith Thompson wrote:
printf is a variadic function, so the types of the arguments after
the format string are not specified in its declaration. The printf
function has to *assume* that arguments have the types specified
by the format string. This:
printf("%d\n", foo);
(probably) has undefined behavior if foo is of type size_t.
And isn't that a nightmare?
We just can't have size_t variables swilling around in prgrams for these >reasons.
On 6/13/2024 3:25 AM, Ike Naar wrote:
On 2024-06-12, DFS <[email protected]> wrote:
//no outliers
if ( min > lo && max < hi) {
The condition for 'no outliers' is not the complement of
the condition for 'at least one outlier' below.
You're saying some outliers will not be flagged?
strcat(outliers,"none (using IQR * 1.5 rule)"); >>> }
//at least one outlier
if ( min < lo || max > hi) {
On 6/13/2024 3:25 AM, Ike Naar wrote:
temp[strlen(temp)] = '\0';
This is unnecessary;
sprintf terminates the generated string with a null character.
Thanks.
POSIX defines a set of strings that can be used by a programmer to
specify the format string for size_t on any given implementation.
On Thu, 13 Jun 2024 11:13:04 -0400, DFS wrote:
On 6/13/2024 3:25 AM, Ike Naar wrote:
On 2024-06-12, DFS <[email protected]> wrote:
//no outliers
if ( min > lo && max < hi) {
The condition for 'no outliers' is not the complement of
the condition for 'at least one outlier' below.
You're saying some outliers will not be flagged?
[1] How does the above statement evaluate when (min == low) and (max == hi)?
//at least one outlier
if ( min < lo || max > hi) {
[2] How does the above statement evaluate when (min == low) and (max == hi)?
[3] Given the answers to questions 1 and 2, are there any values that
satisfy /both/ the "no outliers" and "at least one outlier" conditions?
Are there any values that satisfy /neither/ conditions?
[snip]
HTH
Malcolm McLean <[email protected]> writes:
On 13/06/2024 01:33, Keith Thompson wrote:
And isn't that a nightmare?
printf is a variadic function, so the types of the arguments after
the format string are not specified in its declaration. The printf
function has to *assume* that arguments have the types specified
by the format string. This:
printf("%d\n", foo);
(probably) has undefined behavior if foo is of type size_t.
No, because compilers have been able to diagnose mismatches
for more than two decades.
We just can't have size_t variables swilling around in prgrams for these
reasons.
POSIX defines a set of strings that can be used by a programmer to
specify the format string for size_t on any given implementation.
On 13/06/2024 19:01, bart wrote:
And here it just gets even uglier. You also get situations like this:Exactly. We can't have this just to print out an integer.
��� uint64_t i=0;
��� printf("%lld\n", i);
This compiles OK with gcc -Wall, on Windows64. But compile under Linux64
and it complains the format should be %ld. Change it to %ld, and it
complains under Windows.
It can't tell you that you should be using one of those ludicrous macros.
I've also just noticed that 'i' is unsigned but the format calls for
signed. That may or may not be deliberate, but the compiler didn't say
anything.
In Baby X I provide a function called bbx_malloc(). It's is guaranteed
never to return null. Currently it just calls exit() on allocation failure. But it also limits allocation to slightly under INT_MAX. Which should be plenty for a Baby program, and if you want more, you always have big boy's malloc.
But at a stroke, that gets rid of any need for size_t,
and long is very
special purpose (it holds the 32 bit rgba values).
bart <[email protected]> writes:
Meanwhile for over 4 decades I've been able to just write 'print foo'
with no format mismatch, because such a silly concept doesn't exist.
THAT's how you deal with it.
By using a different language, which perhaps you should consider
discussing in a different newsgroup. We discuss C here.
If foo is an int, for example, printf lets you decide how to print
it (leading zeros or spaces, decimal vs. hex vs. octal (or binary
in C23), upper vs. lower case for hex). Perhaps "print foo" in
your language has similar features.
Yes, the fact that incorrect printf format strings cause undefined
behavior, and that that's sometimes difficult to diagnose, is a
language problem. I don't recall anyone saying it isn't. But it's
really not that hard to deal with it as a programmer.
If you have ideas (other than abandoning C) for a flexible
type-safe printing function, by all means share them. What are your suggestions?
foo` is unlikely to be considered practical; I'd want a much more
general mechanism that's not limited to stdio files. Reasonable new
language features that enable type-safe printf-like functions could
be interesting. I'm not aware of any such proposals for C.
We just can't have size_t variables swilling around in prgrams for these >>>> reasons.POSIX defines a set of strings that can be used by a programmer to
specify the format string for size_t on any given implementation.
And here it just gets even uglier. You also get situations like this:
uint64_t i=0;
printf("%lld\n", i);
This compiles OK with gcc -Wall, on Windows64. But compile under
Linux64 and it complains the format should be %ld. Change it to %ld,
and it complains under Windows.
It can't tell you that you should be using one of those ludicrous macros.
And you know why, right? uint64_t is a typedef (an alias) for some
existing type, typically either unsigned long or unsigned long long.
If uint64_t is a typedef for unsigned long long, then i is of type
unsigned long long, and the format string is correct.
Sure, that's a language problem. It's unfortunate that code can be
either valid or a constraint violation depending on how the current implementation defines uint64_t. I just don't spend much time
complaining about it.
I wouldn't mind seeing a new kind of typedef that creates a new type
rather than an alias. Then uint64_t could be a distinct type.
That could cause some problems for _Generic, for example.
C99 added <stdint.h>, defining fixed-width and other integer types using existing language features. Sure, there are some disadvantages in the
way it was done. The alternative, creating new language features, would likely have resulted in the proposal not being accepted until some time
after C99, if ever.
I've also just noticed that 'i' is unsigned but the format calls for
signed. That may or may not be deliberate, but the compiler didn't say
anything.
The standard allows using an argument of an integer type with a format
of the corresponding type of the other signedness, as long as the value
is in the range of both. (I vaguely recall the standard's wording being
a bit vague on this point.)
On 14/06/2024 00:55, Ben Bacarisse wrote:
Malcolm McLean <[email protected]> writes:But these are not Baby X functions.
On 13/06/2024 19:01, bart wrote:This is how C works. There's no point in moaning about it. Use another
And here it just gets even uglier. You also get situations like this:Exactly. We can't have this just to print out an integer.
��� uint64_t i=0;
��� printf("%lld\n", i);
This compiles OK with gcc -Wall, on Windows64. But compile under Linux64 >>>> and it complains the format should be %ld. Change it to %ld, and it
complains under Windows.
It can't tell you that you should be using one of those ludicrous macros. >>>> I've also just noticed that 'i' is unsigned but the format calls for
signed. That may or may not be deliberate, but the compiler didn't say >>>> anything.
language or do what you have to in C.
In Baby X I provide a function called bbx_malloc(). It's is guaranteedAnd if you need to change the size?
never to return null. Currently it just calls exit() on allocation failure. >>> But it also limits allocation to slightly under INT_MAX. Which should be >>> plenty for a Baby program, and if you want more, you always have big boy's >>> malloc.
But at a stroke, that gets rid of any need for size_t,But sizeof, strlen (and friends like the mbs... and wcs... functions),
strspn (and friend), strftime, fread, fwrite. etc. etc. all return
size_t.
No, because we store images as unsigned char buffers. But it's convenientand long is veryIsn't that rather wasteful when long is 64 bits?
special purpose (it holds the 32 bit rgba values).
to pass around coulor values in a single variable.
However there is the worry that accessing rgba channels as bytes rather
than insisting that the buffer be aligned, and accessing as a 32-bit
value,
Yes, I really need to get that website together so that people cotton on
to what Baby X is, what it can and cannot do, and what is the point.
David Brown <[email protected]> writes:
[...]
Certainly "-O3" is rarely worth it unless you are also using a
"-march=" flag (such as "-fmarch=native") to tune for a particular
processor and enable stuff like vectorisation. Getting the fastest
code is more of an art than a science!
Typo: it's "-march=native".
bart <[email protected]> writes:
On 13/06/2024 16:39, Scott Lurndal wrote:
Malcolm McLean <[email protected]> writes:
On 13/06/2024 01:33, Keith Thompson wrote:
If foo is an int, for example, printf lets you decide how to print
it (leading zeros or spaces, decimal vs. hex vs. octal (or binary
in C23), upper vs. lower case for hex). Perhaps "print foo" in
your language has similar features.
Yes, the fact that incorrect printf format strings cause undefined
behavior, and that that's sometimes difficult to diagnose, is a
language problem. I don't recall anyone saying it isn't. But it's
really not that hard to deal with it as a programmer.
If you have ideas (other than abandoning C) for a flexible
type-safe printing function, by all means share them. What are your suggestions? Adding `print` as a new keyword so you can use `print
foo` is unlikely to be considered practical; I'd want a much more
general mechanism that's not limited to stdio files. Reasonable new
language features that enable type-safe printf-like functions could
be interesting. I'm not aware of any such proposals for C.
I wouldn't mind seeing a new kind of typedef that creates a new type
rather than an alias. Then uint64_t could be a distinct type.
That could cause some problems for _Generic, for example.
On 13/06/2024 16:38, DFS wrote:
What programming language do you usually use? And why are you writing
in C instead? (Or do you simply not do much programming?)
I write a little code every few days. Mostly python.
Certainly if I wanted to calculate some statistics from small data sets,
I'd go for Python - it would not consider C unless it was for an
embedded system.
On 6/13/2024 9:21 AM, David Brown wrote:
On 13/06/2024 00:34, DFS wrote:
On 6/12/2024 6:22 PM, Keith Thompson wrote:
Janis Papanagnou <[email protected]> writes:
On 12.06.2024 22:47, DFS wrote:[...]
[...]before: char outliers[100];
after : char outliers[100] = "";
Seriously; why do you expect [in C] a declaration to initialize that >>>>> stack object? (There are other languages that do initializations as
the language defines it, but C doesn't; it may help to learn before
programming in any language?) And why do you think that "" would be
an appropriate initialization (i.e. a single '\0' character) and not >>>>> all 100 elements set to '\0'? (Someone else might want to access the >>>>> element 'answer[99]'.) And should we pay for initializing 1000000000 >>>>> characters in case one declares an appropriate huge array?
This:
char outliers[100] = "";
initializes all 100 elements to zero. So does this:
char outliers[100] = { '\0' };
Any elements or members not specified in an initializer are set to
zero.
Yes. It's good to point that out, since people might assume that
using a string literal here only initialises the bit covered by that
string literal.
(In C23 you can also write "char outliers[100] = {};" to get all zeros.)
If you want to set an array's 0th element to 0 and not waste time
initializing the rest, you can assign it separately:
char outliers[100];
outliers[0] = '\0';
or
char outliers[100];
strcpy(outliers, "");
though the overhead of the function call is likely to outweigh the
cost of initializing the array.
A good compiler will generate the same code for both cases - strcpy()
is often inlined for such uses.
Thanks. I'll have to remember these things. I like to use char arrays. >>>
The problem is I don't use C very often, so I don't develop muscle
memory.
What programming language do you usually use? And why are you writing
in C instead? (Or do you simply not do much programming?)
I write a little code every few days. Mostly python.
I like C for it's blazing speed. Very addicting. And it's much more challenging/frustrating than python.
I coded a subset (8 stat measures) of this C program 3.5 years ago, and recently decided to finish duplicating all 23 stats shown at:
https://www.calculatorsoup.com/calculators/statistics/descriptivestatistics.php
Working on the outliers code, I decided to add an option to generate
data with consecutive numbers. That's when I ran $./dfs 50 -c and
noticed every value above 40 was considered an outlier. And this didn't change over a bunch of code edits/file saves/compiles.
Understanding how an uninitialized variable caused that persistent issue
is beyond my pay grade.
That's when I whined to clc. Before I even posted, though, I spotted
the uninitialized var (outliers). Later I spotted another one (mode).
One led to 'undefined behavior', the other to 'stack smashing'. Both
only occurred when using consecutive numbers.
But with y'all's help I believe I found and fixed ALL issues. I can
dream anyway.
Baby X FS - the filing system - code that allows you to create a
virtual drive on your computer and access files from it using special fopen(), fclose() functions, but standard library functions like
fprintf() or fgetc() for the other operations
On 14/06/2024 12:44, Ben Bacarisse wrote:
Malcolm McLean <[email protected]> writes:Yes, I really need to get that website together so that people cotton on to what Baby X is, what it can and cannot do, and what is the point.
On 14/06/2024 00:55, Ben Bacarisse wrote:Neither is malloc but you wanted t replace that to get rid of the need
Malcolm McLean <[email protected]> writes:But these are not Baby X functions.
On 13/06/2024 19:01, bart wrote:This is how C works. There's no point in moaning about it. Use another >>>> language or do what you have to in C.
And here it just gets even uglier. You also get situations like this: >>>>>> ��� uint64_t i=0;Exactly. We can't have this just to print out an integer.
��� printf("%lld\n", i);
This compiles OK with gcc -Wall, on Windows64. But compile under Linux64 >>>>>> and it complains the format should be %ld. Change it to %ld, and it >>>>>> complains under Windows.
It can't tell you that you should be using one of those ludicrous macros.
I've also just noticed that 'i' is unsigned but the format calls for >>>>>> signed. That may or may not be deliberate, but the compiler didn't say >>>>>> anything.
In Baby X I provide a function called bbx_malloc(). It's is guaranteed >>>>> never to return null. Currently it just calls exit() on allocation failure.And if you need to change the size?
But it also limits allocation to slightly under INT_MAX. Which should be >>>>> plenty for a Baby program, and if you want more, you always have big boy's
malloc.
But at a stroke, that gets rid of any need for size_t,But sizeof, strlen (and friends like the mbs... and wcs... functions), >>>> strspn (and friend), strftime, fread, fwrite. etc. etc. all return
size_t.
for size_t.
I confess that I am all at sea about what you are doing. In essence, I
don't understand the rules of the game so I should probably just stop
commenting.
However if you need to pass a colour value to a fuction, you normall pass a BBX_RGBA value, which is typedefed to unsigned long, and is opaque, and you query the channels using the macros in bbx_color.h
#ifndef bbx_color_h
#define bbx_color_h
typedef unsigned long BBX_RGBA;
#define bbx_rgba(r,g,b,a) ((BBX_RGBA) ( ((r) << 24) | ((g) << 16) | ((b) << 8) | (a) ))
#define bbx_rgb(r, g, b) bbx_rgba(r,g,b, 255)
#define bbx_red(col) ((col >> 24) & 0xFF)
#define bbx_green(col) ((col >> 16) & 0xFF)
#define bbx_blue(col) ((col >> 8) & 0xFF)
#define bbx_alpha(col) (col & 0xFF)
#define BBX_RgbaToX(col) ( (col >> 8) & 0xFFFFFF )
#endif
The last macro is to make it easier to interface with Xlib, and has the prefix BBX_ (upper case) indicating that it is for internal use by the bbx library / system and not meant for user programs.
Fwiw, I remember doing a channel based hit map that stored an image using RGBA but used floats. Each pixel would have a hit:
struct hit
{
float m_color[4];
};
It would take all of the hits and depending on what was going on during iteration it would increment parts of hit::m_color[4].
On 13/06/2024 16:38, DFS wrote:
I write a little code every few days. Mostly python.
Certainly if I wanted to calculate some statistics from small data sets,
I'd go for Python - it would not consider C unless it was for an
embedded system.
I like C for it's blazing speed. Very addicting. And it's much more
challenging/frustrating than python.
With small data sets, Python has blazing speed - /every/ language has
blazing speed. And for large data sets, use numpy on Python and you
/still/ have blazing speeds - a lot faster than anything you would write
in C (because numpy's underlying code is written in C by people who are
much better at writing fast numeric code than you or I).
The only reason to use C for something like is is for the challenge and
fun, which is fair enough.
On 14/06/2024 22:29, Ben Bacarisse wrote:
Malcolm McLean <[email protected]> writes:
On 14/06/2024 12:44, Ben Bacarisse wrote:I know what Baby X is. I don't know why "these are not Baby X
Malcolm McLean <[email protected]> writes:Yes, I really need to get that website together so that people cotton on to >>> what Baby X is, what it can and cannot do, and what is the point.
On 14/06/2024 00:55, Ben Bacarisse wrote:Neither is malloc but you wanted t replace that to get rid of the need >>>> for size_t.
Malcolm McLean <[email protected]> writes:But these are not Baby X functions.
On 13/06/2024 19:01, bart wrote:This is how C works. There's no point in moaning about it. Use another >>>>>> language or do what you have to in C.
And here it just gets even uglier. You also get situations like this: >>>>>>>> ��� uint64_t i=0;Exactly. We can't have this just to print out an integer.
��� printf("%lld\n", i);
This compiles OK with gcc -Wall, on Windows64. But compile under Linux64
and it complains the format should be %ld. Change it to %ld, and it >>>>>>>> complains under Windows.
It can't tell you that you should be using one of those
ludicrous macros.
I've also just noticed that 'i' is unsigned but the format calls for >>>>>>>> signed. That may or may not be deliberate, but the compiler didn't say >>>>>>>> anything.
In Baby X I provide a function called bbx_malloc(). It's is guaranteed >>>>>>> never to return null. Currently it just calls exit() onAnd if you need to change the size?
allocation failure.
But it also limits allocation to slightly under INT_MAX. Which should be
plenty for a Baby program, and if you want more, you always
have big boy's
malloc.
But at a stroke, that gets rid of any need for size_t,But sizeof, strlen (and friends like the mbs... and wcs... functions), >>>>>> strspn (and friend), strftime, fread, fwrite. etc. etc. all return >>>>>> size_t.
I confess that I am all at sea about what you are doing. In essence, I >>>> don't understand the rules of the game so I should probably just stop
commenting.
functions" applies to the ones I listed and not to malloc.
...
However if you need to pass a colour value to a fuction, you normall pass a >>> BBX_RGBA value, which is typedefed to unsigned long, and is opaque, and you >>> query the channels using the macros in bbx_color.h
#ifndef bbx_color_h
#define bbx_color_h
typedef unsigned long BBX_RGBA;
Curious. The macros below seem to assume that int is 32 bits, so why
use long?
#define bbx_rgba(r,g,b,a) ((BBX_RGBA) ( ((r) << 24) | ((g) << 16) | ((b) << >>> 8) | (a) ))This is likely to involve undefined behaviour when r >= 128. (I presume
you are ruling out int narrower than 32 bits or there are other problems
as well.)
No, it's been miswritten. Which is what I mean about C's integer types
being a source of bugs. That code does not look buggy, but it is.
#define bbx_rgb(r, g, b) bbx_rgba(r,g,b, 255)It might not be an issue (as col is opaque and unlikely to be an
#define bbx_red(col) ((col >> 24) & 0xFF)
#define bbx_green(col) ((col >> 16) & 0xFF)
#define bbx_blue(col) ((col >> 8) & 0xFF)
#define bbx_alpha(col) (col & 0xFF)
expression) but I'd still write (col) here to stop the reader having to
check or reason that out.
#define BBX_RgbaToX(col) ( (col >> 8) & 0xFFFFFF )
#endif
The last macro is to make it easier to interface with Xlib, and has the
prefix BBX_ (upper case) indicating that it is for internal use by the bbx >>> library / system and not meant for user programs.
As a reader of the code, I made exactly the reverse assumption. When I
see lower-case macros I assume they are for internal use.
They're function-like macros. Iterating over an rgba buffer is very processor-intensive, and so we do haave to compromise sfatety for speed
here.
All function-like symbols bbx_ are provided by Baby X for users, all
symbols BBX_ have that prefix to reduce the chance of collisions with other code.
DFS <[email protected]> writes:
[...]
During conversion, I got a Python error I don't remember seeing in the past: >>[...]
"TypeError: list indices must be integers or slices, not float"
because division returns a float, and some of the array addressing was
like this: nums[i/2].
C's "/" operator yields a result with the type of the operands (after promotion to a common type).
Python's "/" operator yields a floating-point result. For C-style
integer division, Python uses "//". (Python 2 is more C-like.)
DFS <[email protected]> writes:If i
On 6/14/2024 9:39 PM, Keith Thompson wrote:
DFS <[email protected]> writes:
[...]
During conversion, I got a Python error I don't remember seeing in the past:[...]
"TypeError: list indices must be integers or slices, not float"
because division returns a float, and some of the array addressing was >>>> like this: nums[i/2].
C's "/" operator yields a result with the type of the operands
(after
promotion to a common type).
Python's "/" operator yields a floating-point result. For C-style
integer division, Python uses "//". (Python 2 is more C-like.)
I was surprised python did that, since every division used in the
array addressing results in an integer.
After casting i to an int before any array addressing, // works.
I'm surprised you needed to convert i to an int. I would think that
just replacing nums[i/2] by nums[i//2] would do the trick,
as long> as i always has an int value (note Python's dynamic typing).
is acquiring a float value, that's probably a bug, given the name.
But if you want help with your Python code, comp.lang.python is the
place to ask.
On 6/14/2024 11:56 PM, Keith Thompson wrote:
DFS <[email protected]> writes:
After casting i to an int before any array addressing, // works.
I'm surprised you needed to convert i to an int. I would think that
just replacing nums[i/2] by nums[i//2] would do the trick,
as long as i always has an int value (note Python's dynamic typing).
If i is acquiring a float value, that's probably a bug, given the name.
I spotted the issue. Just prior to using i for array addressing I said:
i = N/2.
The fix is set i = int(N/2)
On 6/14/2024 11:56 PM, Keith Thompson wrote:...
DFS <[email protected]> writes:
On 6/14/2024 9:39 PM, Keith Thompson wrote:
I'm surprised you needed to convert i to an int. I would think thatIf i
just replacing nums[i/2] by nums[i//2] would do the trick,
as long> as i always has an int value (note Python's dynamic typing).
is acquiring a float value, that's probably a bug, given the name.
I spotted the issue. Just prior to using i for array addressing I said:
i = N/2.
The fix is set i = int(N/2)
But if you want help with your Python code, comp.lang.python is the
place to ask.
Thanks for your help, but David Brown is a Python developer and I'll ask
him python questions here whenever I care to.
On 6/14/2024 11:56 PM, Keith Thompson wrote:
DFS <[email protected]> writes:If i
On 6/14/2024 9:39 PM, Keith Thompson wrote:
DFS <[email protected]> writes:
[...]
During conversion, I got a Python error I don't remember seeing in[...]
the past:
"TypeError: list indices must be integers or slices, not float"
because division returns a float, and some of the array addressing was >>>>> like this: nums[i/2].
C's "/" operator yields a result with the type of the operands
(after
promotion to a common type).
Python's "/" operator yields a floating-point result. For C-style
integer division, Python uses "//". (Python 2 is more C-like.)
I was surprised python did that, since every division used in the
array addressing results in an integer.
After casting i to an int before any array addressing, // works.
I'm surprised you needed to convert i to an int. I would think that
just replacing nums[i/2] by nums[i//2] would do the trick,
as long> as i always has an int value (note Python's dynamic typing).
is acquiring a float value, that's probably a bug, given the name.
I spotted the issue. Just prior to using i for array addressing I said:
i = N/2.
The fix is set i = int(N/2)
But if you want help with your Python code, comp.lang.python is the
place to ask.
Thanks for your help, but David Brown is a Python developer and I'll ask
him python questions here whenever I care to.
In the recent past you were involved in discussions on perl, Fortran and
awk, among other off-topics.
Rules for thee but not for me?
On 15.06.2024 06:45, DFS wrote:
On 6/14/2024 11:56 PM, Keith Thompson wrote:
DFS <[email protected]> writes:
After casting i to an int before any array addressing, // works.
I'm surprised you needed to convert i to an int. I would think that
just replacing nums[i/2] by nums[i//2] would do the trick,
as long as i always has an int value (note Python's dynamic typing).
If i is acquiring a float value, that's probably a bug, given the name.
I spotted the issue. Just prior to using i for array addressing I said:
i = N/2.
The fix is set i = int(N/2)
Given what Keith suggested, and assuming N is an integer, wouldn't it
be more sensible to use the int division operator '//' and just write
i = N // 2 ? I mean, why do a float division on integer operands and
then again coerce the result to int again?
On 14/06/2024 22:29, Ben Bacarisse wrote:
Malcolm McLean <[email protected]> writes:
On 14/06/2024 12:44, Ben Bacarisse wrote:
Malcolm McLean <[email protected]> writes:Yes, I really need to get that website together so that people cotton
On 14/06/2024 00:55, Ben Bacarisse wrote:Neither is malloc but you wanted t replace that to get rid of the need >>>> for size_t.
Malcolm McLean <[email protected]> writes:But these are not Baby X functions.
On 13/06/2024 19:01, bart wrote:This is how C works. There's no point in moaning about it. Use >>>>>> another
And here it just gets even uglier. You also get situations like >>>>>>>> this:Exactly. We can't have this just to print out an integer.
uint64_t i=0;
printf("%lld\n", i);
This compiles OK with gcc -Wall, on Windows64. But compile under >>>>>>>> Linux64
and it complains the format should be %ld. Change it to %ld, and it >>>>>>>> complains under Windows.
It can't tell you that you should be using one of those
ludicrous macros.
I've also just noticed that 'i' is unsigned but the format calls >>>>>>>> for
signed. That may or may not be deliberate, but the compiler
didn't say
anything.
language or do what you have to in C.
In Baby X I provide a function called bbx_malloc(). It's isAnd if you need to change the size?
guaranteed
never to return null. Currently it just calls exit() on
allocation failure.
But it also limits allocation to slightly under INT_MAX. Which
should be
plenty for a Baby program, and if you want more, you always have >>>>>>> big boy's
malloc.
But at a stroke, that gets rid of any need for size_t,But sizeof, strlen (and friends like the mbs... and wcs...
functions),
strspn (and friend), strftime, fread, fwrite. etc. etc. all return >>>>>> size_t.
I confess that I am all at sea about what you are doing. In essence, I >>>> don't understand the rules of the game so I should probably just stop
commenting.
on to
what Baby X is, what it can and cannot do, and what is the point.
I know what Baby X is. I don't know why "these are not Baby X
functions" applies to the ones I listed and not to malloc.
...
However if you need to pass a colour value to a fuction, you normall
pass a
BBX_RGBA value, which is typedefed to unsigned long, and is opaque,
and you
query the channels using the macros in bbx_color.h
#ifndef bbx_color_h
#define bbx_color_h
typedef unsigned long BBX_RGBA;
Curious. The macros below seem to assume that int is 32 bits, so why
use long?
#define bbx_rgba(r,g,b,a) ((BBX_RGBA) ( ((r) << 24) | ((g) << 16) |
((b) <<
8) | (a) ))
This is likely to involve undefined behaviour when r >= 128. (I presume
you are ruling out int narrower than 32 bits or there are other problems
as well.)
No, it's been miswritten. Which is what I mean about C's integer types
being a source of bugs. That code does not look buggy, but it is.
#define bbx_rgb(r, g, b) bbx_rgba(r,g,b, 255)
#define bbx_red(col) ((col >> 24) & 0xFF)
#define bbx_green(col) ((col >> 16) & 0xFF)
#define bbx_blue(col) ((col >> 8) & 0xFF)
#define bbx_alpha(col) (col & 0xFF)
It might not be an issue (as col is opaque and unlikely to be an
expression) but I'd still write (col) here to stop the reader having to
check or reason that out.
#define BBX_RgbaToX(col) ( (col >> 8) & 0xFFFFFF )
#endif
The last macro is to make it easier to interface with Xlib, and has the
prefix BBX_ (upper case) indicating that it is for internal use by
the bbx
library / system and not meant for user programs.
As a reader of the code, I made exactly the reverse assumption. When I
see lower-case macros I assume they are for internal use.
They're function-like macros. Iterating over an rgba buffer is very processor-intensive, and so we do haave to compromise sfatety for speed
here. All function-like symbols bbx_ are provided by Baby X for users,
all symbols BBX_ have that prefix to reduce the chance of collisions
with other code.
If you want BBX_RGBA to be a typedef for an unsigned 32-bit integer, write:
typedef uint32_t BBX_RGBA;
If you want bbx_rgba() to be a function that is typesafe, correct, and efficient (for any decent compiler), write :
static inline BBX_RGBA bbx_rgba(uint32_t r, uint32_t g,
uint32_t b, uint32_t a)
{
return (r << 24) | (g << 16) | (b << 8) | a;
}
David Brown <[email protected]> writes:
On 13/06/2024 16:38, DFS wrote:
What programming language do you usually use? And why are you writing >>>> in C instead? (Or do you simply not do much programming?)
I write a little code every few days. Mostly python.
Certainly if I wanted to calculate some statistics from small data sets,
I'd go for Python - it would not consider C unless it was for an
embedded system.
I'd likely turn to R instead of Python for that.
David Brown <[email protected]> writes:
On 14/06/2024 00:58, Keith Thompson wrote:
bart <[email protected]> writes:
On 13/06/2024 16:39, Scott Lurndal wrote:If foo is an int, for example, printf lets you decide how to print
Malcolm McLean <[email protected]> writes:
On 13/06/2024 01:33, Keith Thompson wrote:
it (leading zeros or spaces, decimal vs. hex vs. octal (or binary
in C23), upper vs. lower case for hex). Perhaps "print foo" in
your language has similar features.
C23 also adds explicit width length modifiers. So instead of having
to guess if uint64_t is "%llu" or "%lu" on a particular platform, or
using the PRIu64 macro, you can now use "%w64u" for uint64_t (or
uint_least64_t if the exact width type does not exist). I think
that's about as neat as you could get, within the framework of printf.
Note that the new "%wN" modifier applies only to [u]intN_t and [u]int_leastN_t types, not to all integer types with a width of N bits.
The standard doesn't guarantee that integer types with the same representation are interchangeable, so for example printf("%d", 0L) and printf("%ld", 0) both have undefined behavior. An implementation would probably have to go out of its way to make either of those do anything
other than printing "0", but the behavior is still undefined (i.e., the standard doesn't guarantee it will work).
That's still the case in C23, even for the %wN modifiers. For a typical implementation with 32-bit integer types, uint32_t and uint_least32_t
will be the same type (C17 doesn't require that), and "%w32u" will work
with that type. It's not guaranteed to work with any other 32-bit
unsigned type. For an implementation that doesn't have any 32-bit
integer type, uint32_t won't exist, uint_least32_t will be, say, 64
bits, and "%w32u" will work with *that* type.
That covers the exact-width and "least" types. The "%wfN" modifiers
cover the "fast" types.
So if you want to use C23's new "%wN" modifiers, you have to use the
types defined in <stdint.h> if you want to avoid undefined behavior.
On the other hand, though `int n = 42; printf("%w32d\n", n);` has
undefined behavior, it's very very likely to work if int is 32 bits.
(`gcc -Wformat` warns about using "%ld" with a long long argument
even when long and long long have the same size, but not about using
"%w32d" with a 32-bit int argument.)
The new modifiers are supported in glibc 2.39, which is included in
Ubuntu 24.04. They're not supported in newlib (used by Cygwin) or in
MS Visual Studio 2022.
[...]
I wouldn't mind seeing a new kind of typedef that creates a new type
rather than an alias. Then uint64_t could be a distinct type.
That could cause some problems for _Generic, for example.
I too would like such a typedef. Using it for uint64_t would cause
problems for /existing/ uses of _Generic, but would make future uses
better.
Currently, there are (in the absence of extended integer types) only a
finite number of incompatible integer types. This makes it possible to
write a _Generic expression that accepts an operand of any integer type, which can be useful if you have an integer typedef and don't know the underlying type. This new kind of typedef would allow programmers to introduce an unlimited number of new incompatible integer types.
I haven't seen a lot of code that does that kind of thing, and none
that I didn't write myself.
Perhaps if this is introduced, there should be a way to determine the underlying type. C23 introduces typeof and typeof_unqual; perhaps we
could have typeof_underlying. It could also apply to enum types.
On 6/14/2024 11:56 PM, Keith Thompson wrote:
DFS <[email protected]> writes:If i
On 6/14/2024 9:39 PM, Keith Thompson wrote:
DFS <[email protected]> writes:
[...]
During conversion, I got a Python error I don't remember seeing in[...]
the past:
"TypeError: list indices must be integers or slices, not float"
because division returns a float, and some of the array addressing was >>>>> like this: nums[i/2].
C's "/" operator yields a result with the type of the operands
(after
promotion to a common type).
Python's "/" operator yields a floating-point result. For C-style
integer division, Python uses "//". (Python 2 is more C-like.)
I was surprised python did that, since every division used in the
array addressing results in an integer.
After casting i to an int before any array addressing, // works.
I'm surprised you needed to convert i to an int. I would think that
just replacing nums[i/2] by nums[i//2] would do the trick,
as long> as i always has an int value (note Python's dynamic typing).
is acquiring a float value, that's probably a bug, given the name.
I spotted the issue. Just prior to using i for array addressing I said:
i = N/2.
The fix is set i = int(N/2)
But if you want help with your Python code, comp.lang.python is the
place to ask.
Thanks for your help, but David Brown is a Python developer and I'll ask
him python questions here whenever I care to.
In the recent past you were involved in discussions on perl, Fortran and
awk, among other off-topics.
Rules for thee but not for me?
On 15/06/2024 19:57, David Brown wrote:
If you want BBX_RGBA to be a typedef for an unsigned 32-bit integer,
write:
����typedef uint32_t BBX_RGBA;
If you want bbx_rgba() to be a function that is typesafe, correct, and
efficient (for any decent compiler), write :
����static inline BBX_RGBA bbx_rgba(uint32_t r, uint32_t g,
����������� uint32_t b, uint32_t a)
����{
������� return (r << 24) | (g << 16) | (b << 8) | a;
����}
Shouldn't that be ... ?
static inline BBX_RGBA bbx_rgba(uint8_t r, uint8_t g,
uint8_t b, uint8_t a)
On 15/06/2024 19:57, David Brown wrote:
If you want BBX_RGBA to be a typedef for an unsigned 32-bit integer,
write:
typedef uint32_t BBX_RGBA;
If you want bbx_rgba() to be a function that is typesafe, correct, and
efficient (for any decent compiler), write :
static inline BBX_RGBA bbx_rgba(uint32_t r, uint32_t g,
uint32_t b, uint32_t a)
{
return (r << 24) | (g << 16) | (b << 8) | a;
}
Shouldn't that be ... ?
static inline BBX_RGBA bbx_rgba(uint8_t r, uint8_t g,
uint8_t b, uint8_t a)
(I'd like to a future standard require plain char to be unsigned,
but I don't know how likely that is.)
Tim Rentsch <[email protected]> writes:
Keith Thompson <[email protected]> writes:
(I'd like to a future standard require plain char to be unsigned,
but I don't know how likely that is.)
It seems unnecessary given that the upcoming C standard
is choosing to mandate two's complement for all signed
integer types.
It's less necessary, but I'd still like to see it.
These days, strings very commonly hold UTF-8 data. The fact that bytes
whose values exceed 127 are negative is conceptually awkward, even if everything happens to work. It rarely if ever makes sense to treat a character value as negative.
(And of course signed char still exists,
or int8_t if you prefer 8 bits vs. CHAR_BIT bits.)
A drawback is that it could break existing (non-portable) code that
assumes plain char is signed.
| Sysop: | Keyop |
|---|---|
| Location: | Huddersfield, West Yorkshire, UK |
| Users: | 715 |
| Nodes: | 16 (3 / 13) |
| Uptime: | 28:29:09 |
| Calls: | 12,107 |
| Calls today: | 7 |
| Files: | 15,006 |
| Messages: | 6,518,231 |