Deutsch   English   Français   Italiano  
<vbor2f$2qqt1$1@dont-email.me>

View for Bookmarking (what is this?)
Look up another Usenet article

Path: ...!2.eu.feeder.erje.net!3.eu.feeder.erje.net!feeder.erje.net!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: David Brown <david.brown@hesbynett.no>
Newsgroups: comp.lang.c
Subject: Re: Top 10 most common hard skills listed on resumes...
Date: Tue, 10 Sep 2024 09:04:47 +0200
Organization: A noiseless patient Spider
Lines: 148
Message-ID: <vbor2f$2qqt1$1@dont-email.me>
References: <vab101$3er$1@reader1.panix.com> <vbepcb$q6p2$1@dont-email.me>
 <vbgb5q$1ruv8$1@paganini.bofh.team> <vbhbbb$1blt4$1@dont-email.me>
 <vbipp5$24kl5$1@paganini.bofh.team> <vbk0d9$1tajm$1@dont-email.me>
 <vbkpfc$27l2o$1@paganini.bofh.team> <vbl3am$228vv$1@dont-email.me>
 <vblfgb$2dkij$1@paganini.bofh.team> <vblhp7$249ug$1@dont-email.me>
 <vbloje$2e34o$1@paganini.bofh.team> <vbmeae$2bn2v$2@dont-email.me>
 <vbn8pe$2g9i6$2@paganini.bofh.team> <vbnaqt$2g0vc$1@dont-email.me>
 <vbnre4$2h8k3$1@paganini.bofh.team>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Tue, 10 Sep 2024 09:04:48 +0200 (CEST)
Injection-Info: dont-email.me; posting-host="164517e557401dcf9b3aeffde6d063fe";
	logging-data="2976673"; mail-complaints-to="abuse@eternal-september.org";	posting-account="U2FsdGVkX193wSUf/vaRog/NlaDkSU8r8VSdqCI+AgI="
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101
 Thunderbird/102.11.0
Cancel-Lock: sha1:ZfgxPrtZ17Mb01iCIqUU0WMGN/Y=
In-Reply-To: <vbnre4$2h8k3$1@paganini.bofh.team>
Content-Language: en-GB
Bytes: 9291

On 10/09/2024 00:04, Waldek Hebisch wrote:
> David Brown <david.brown@hesbynett.no> wrote:
>> On 09/09/2024 18:46, Waldek Hebisch wrote:
>>> David Brown <david.brown@hesbynett.no> wrote:
>>>> On 09/09/2024 05:04, Waldek Hebisch wrote:
>>>>> Bart <bc@freeuk.com> wrote:
>>>>>> On 09/09/2024 01:29, Waldek Hebisch wrote:
>>>>>>> Bart <bc@freeuk.com> wrote:
>>>>>>
>>>>>>> No.  It is essential for efficiency to have 32-bit types.  On 32-bit
>>>>>>> machines doing otherwise would add useless instructions to object
>>>>>>> code.  More precisly, really stupid compiler will generate useless
>>>>>>> intructions even with my declarations, really smart one will
>>>>>>> notice that variables fit in 32-bits and optimize accordingly.
>>>>>>> But at least some gcc versions needed such declarations.  Note
>>>>>>> also that my version makes clear that there there is
>>>>>>> symmetry (everything should be added using 64-bit precision),
>>>>>>> you depend on promotion rules which creates visual asymetry
>>>>>>> are requires reasoning to realize that meaning is symetric.
>>>>>>
>>>>>> Your posted code used 64-bit aritmetic. The xext and c 32-bit variables
>>>>>> were used in loops where they need to be widened to 64 bits anyway. The
>>>>>> new value of c is set from a 32-bit result.
>>>>>
>>>>> Well, at C level there is 64-bit type.  The intent is that C compiler
>>>>> should notice that the result is 32-bit + carry flag.  Ideally
>>>>> compiler should notice that c has only one bit and can keep it
>>>>> in carry flag.  On i386 comparison needed for loop control would
>>>>> destroy carry flag, so there must be code using value of carry in
>>>>> register and code to save carry to register.  But one addition
>>>>> of highs parts can be skipped.  On 32-bit ARM compiler can use
>>>>> special machine istructions and actually generated code which
>>>>> is close to optimal.
>>>>
>>>> When you have a type that you want to be at least 32 bits (to cover the
>>>> range you need), and want it to be as efficient as possible on 32-bit
>>>> and 64-bit machines (and 16-bit and 8-bit, still found in
>>>> microcontrollers), use "int_fast32_t".  On x86-64 it will be 64-bit, on
>>>> 32-bit systems it will be 32-bit.  Use of the [u]int_fastNN_t types can
>>>> make code significantly more efficient on 64-bit systems while retaining
>>>> efficiency on 32-bit (or even smaller) targets.
>>>
>>> Well, I have constraints, some of which are outside of C code.
>>> To resolve contraints I normally use some configure machinery.
>>> If a standard type is exact match for my constraints, then I would
>>> use standard type, possibly adding some fallbacks for pre-standard
>>> systems.  But if my constranits differ, I see no advantage in
>>> using more "fancy" standard types compared to old types.
>>>
>>
>> The "fancy" standard types in this case specify /exactly/ what you
>> apparently want - a type that can deal with at least 32 bits for range,
>> and is as efficient as possible on different targets.  What other
>> constraints do you have here that make "int_fast32_t" unsuitable?
> 
> This routine is part of small library.  Good approximation is that
> I want a type (posibly depending on target) which will make this
> library fast.  As I wrote in another message I plan to use 64-bit
> units of work on 64-bit targets.  I have not plans to use the
> library in 8-bit or 16-bit targets, but if I needed them on such
> targets I probably would use 16-bit work unit.  So, while 32-bit
> work unit represents current state, it not correct statement of
> intentions.  Consequently, 'int_fast32_t' would be as misleading
> or more misleading than 'int' ('int' is reasonable indication
> that choice of types is not finished, 'int_fast32_t' suggest that
> it is proper choice for all targets).

So you really want to say "at least 16 bits, as efficiently as possible" 
- the type then is "int_fast16_t".  This should be 32-bit or 64-bit on 
most architectures bigger than 16-bit - unless the target is actually 
more efficient at handling 16-bit (such as the original 68000).

If something like that is not sufficient, because you want more 
flexibility, then consider making a typedef with a name you find 
suitable, and a using that.  You can have pre-processor conditional 
compilation to handle known cases, and fall back to int_fast16_t otherwise.

The answer to "I don't know if this is the best choice on all targets, 
including ones I haven't tried" is /not/ "I'll use this type that I know 
is not the most efficient on targets that I /have/ tried".

> 
>>> Concerning '<stdint.h>', somewhat worring thing is that several types
>>> there seem to be optional (or maybe where optional in older versions
>>> of the standard).  I am not sure if this can be real problem,
>>> but too many times I saw that on various issues developers say
>>> "this in not mandatory, so we will skip it".
>>>
>>
>> <stdint.h> has been required since C99.  It has not been optional in any
>> C standard in the last 25 years.  That's a /long/ time - long enough for
>> most people to be able to say "it's standard".
>>
>> And almost every C90 compiler also includes <stdint.h> as an extension.
>>
>> If you manage to find a compiler that is old enough not to have
>> <stdint.h>, and you need to use it for actual code, it's probably worth
>> spending the 3 minutes it takes to write a suitable <stdint.h> yourself
>> for that target.
> 
> ATM I do not have standard text handy to check, but AFAIR several
> _types_ in <stdint.h> were not required but optional.
> 

Online versions of the standards - at least from C99 upwards - are 
easily and freely available, as long as you are happy with the final 
pre-published drafts rather than insisting on the expensive official 
documents:

<https://en.cppreference.com/w/c/links>

Or you can ask here, and be sure that someone will tell you the answer. 
And if that answer is incorrect or imprecise, someone else will correct 
it :-)

The exact size types - int8_t, uint16_t, etc., might not exist on a 
given target (some DSP's have CHARBIT 16 or 32, for example).  The exact 
width types for sizes 8, 16, 32, and 64 are required if the 
implementation has standard or extended integer types of those sizes and 
properties (no padding bits, two's complement representation). 
Otherwise they are optional.  Other sizes are always optional - if an 
implementation has 24-bit int, it still does not have to provide 
int24_t, though it is good practice.

So the 8, 16, 32, and 64 exact size types are always available if the 
target supports them, and that is /almost/ always the case.

The [u]int_leastN_t and [u]int_fastN_t types are always required for 8, 
16, 32 and 64 bit.  Other sizes are optional.

[u]intptr_t are optional, but almost always provided.  [u]intmax_t are 
required.


So you can freely use the "least" and "fast" types for sizes 8, 16, 32, 
and 64 on any platform, knowing they always exist (for C99 upwards). 
The fixed size types (for these standard sizes) will exist on all but 
the most unusual of C targets, and if you are working with such a 
target, you would already know about it.

If you need to convert a pointer to an integer type, use "uintptr_t" - 
if that type does not exist, you are probably on a specialist target 
that has some kind of long pointer and the conversion to an integer is 
unlikely to work well anyway.

(It is conceivable that a pre-C99 implementation will provide a partial 
<stdint.h> with the fixed size types and not the least or fast types.)