From: Keith.S.Thompson+u@gmail.com
bart writes:
> On 01/12/2025 04:10, Waldek Hebisch wrote:
>> bart wrote:
>>> On 01/12/2025 00:08, Waldek Hebisch wrote:
>>>> bart wrote:
>>>>>
>>>>> Yet what I said is pretty much true. Nobody care about BitInt until they
>>>>> became aware of, and now it's must-have.
They're a must-have if you want a conforming C23 implementation.
I don't recall anyone saying they're a "must-have" for any other
reason. But if you assert that everyone else things _BitInt types
were an absolutely necessary feature to add to the language, it
gives you something to argue against.
>>>> Well, you were told many times that regulars here know deficiencies
>>>> of C. "Nobody care about BitInt" in the sense that before _BitInt
>>>> people will say "this can not be expressed directly in C, you need
>>>> such and such workaround". People did not loudly complain
>>>> knowing that complaints would achive nothing. But say doing
>>>> language comparisons they could note that C lack such a feature.
>>>>
>>>> There is also a psychological phenomenon: computers even in crude
>>>> form are quite useful. So people were willing to jump hops to
>>>> use them. But when better/easier approach is available people
>>>> wery strongly resist going to old ways. So, once w got _BitInt
>>>> you will not be able to take it back.
>>>
>>> I've been claiming that _BitInt was a poor fit for a language at the
>>> level of C which lacks some more fundamental features.
>>>
>>> But I think I was wrong: the way _BitInt has been devised and presented
>>> is actually completely in line with the haphazard way C has evolved up
>>> to now.
>>>
>>> I made the mistake in this thread of thinking that people cared about
>>> measured language design; obviously if they're using C, they don't.
Here you make the mistake of assuming that everyone who disagrees
with you doesn't care about language design. You fail to consider
the possibility that someone can (a) care about language design *and*
(b) be willing to accept the design of C as it is, even with its flaws.
>>> unsigned char* p;
>>> uint8_t* q; // only exists when stdint.h used
>>> unsigned _BitInt(8)* r;
>>> char* s;
>>>
>>> p and q are probably compatible. p and r are not; q and r and not. s is
>>> incompatible with p, q, r even if it is unsigned.
I've asked you before why it matters to you that some of these types are
incompatible.
>> Do you understand that uint8_t and _BitInt(8) are different types?
>
> Well, apparently they aren't. It's not immediately obvious why, but as
> I explained above, I realise this is entirely in keeping with how C
> works.
>
>> And the difference is not an accident, but they have different
>> properties (uint8_t in expressions promotes to int, _BitInt(8)
>> is not subject to this promotion).
>
> This is another little rule that is not obvious, and out of keeping
> with how other types work. Yet add _BitInt(8) to _BitInt(16), and one
> side /is/ promoted.
And this is all specified in the standard. The *integer promotions*
convert a value of any narrow integer type other than a bit-precise type
to int or unsigned int; they do not apply to bit-precise types. The
*usual arithmetic conversions* resolve the left and right operands of an
operator to the same type.
The fact that bit-precise integer types are not subject to the integer
promotions *is* obvious. It's clearly stated in the C23 standard.
> My example was just to highlight the plethora of type denotations that
> exist, even for the same machine type. The rules for
> type-compatibility and promotions (and the ugly syntax) is just icing
> on top.
>
> This ungainly way to evolve a language is how C works (just look at
> all the things wrong with how stdint.h types were handled).
>
> The following table for example shows the rules for mixed sign
> arithmetic: S means the result (32 or 64 bits) has signed type, and u
> means it is unsigned:
>
> u8 u16 u32 u64 i8 i16 i32 i64
>
> u8 S S u u S S S S
> u16 S S u u S S S S
> u32 u u u u u u u S
> u64 u u u u u u u u
>
> i8 S S u u S S S S
> i16 S S u u S S S S
> i32 S S u u S S S S
> i64 S S S u S S S S
>
> But of course, every C programmer knows this and doesn't need such a chart!
I'm not going to take the time to confirm that your chart is correct.
It assumes that int is 32 bits; an implementation with 16-bit or
64-bit int would require a different chart.
But the fact that you were able to generate the chart means that
*you already understand the rules*. You just choose to express
those rules in a way that's more confusing.
> Here, i8 + u8 gives a signed result; but 'unsigned _BitInt(8 ) +
> _Bitint(8)' apparently gives an unsigned result (tested using
> _Generic).
Yes. That follows from the language rules, and in particular the
fact that the new bit-precise types are not subject to the integer
promotions. But citing a special case of those rules and taking
it out of context just makes the rules seem more confusing --
deliberately, I presume.
Am I happy about the C conversion rules? Not entirely.
The ANSI C committee had to choose between value-preserving and
unsigned-preserving semantics (both choices had been made by existing
compilers). I tend to think that unsigned-preserving rules would
have been better. And the fact that types narrower than int are
promoted before they can be operated on also strikes me as a bit
iffy; I think that, for example, having operations on two short
int operands yield a short int result would have been cleaner.
But I'm far more interested in understanding and explaining the
existing rules than in complaining about them. And the rules can't
be changed without breaking existing code.
> So another plus point for staying close to the C spirit!
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
void Void(void) { Void(); } /* The recursive call of the void */
--- SoupGate-Win32 v1.05
* Origin: you cannot sedate... all the things you hate (1:229/2)
|