EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

Delay Routine: Fully-portable C89 if possible

Started by Martin Wells October 9, 2007
Grant Edwards <grante@visi.com> writes:

> On 2007-10-13, Martin Wells <warint@eircom.net> wrote: >> David: >> >>> That is why the <stdint.h> types >>> were defined, and that is why they are important if you want portable >>> code that works on a wide range of targets (at least, for architectures >>> that can support 8, 16 and 32-bit data - targets with 36 bit cpus, for >>> example, will always be problematic for portable code). >> >> >> For what purposes would you want an integer type of a given >> size (other than an integer type of *at least* a given size)? > > When you want perform modulo-N arithmetic.
Hmm.. don't the low-order N bits of an unsigned always obey modulo-N arithmetic? I.e, use the "guaranteed long enough" type then mask at the point of use. For example you could do uint8_t index; ... index++; buffer[index] = c; or unsigned char index; ... index++; buffer[index&0xff] = c; The compiler should optimize this to the same code. Also this way I can use other masks for different N. -- John Devereux
On 2007-10-13, John Devereux <jdREMOVE@THISdevereux.me.uk> wrote:
> Grant Edwards <grante@visi.com> writes: > >> On 2007-10-13, Martin Wells <warint@eircom.net> wrote: >>> David: >>> >>>> That is why the <stdint.h> types >>>> were defined, and that is why they are important if you want portable >>>> code that works on a wide range of targets (at least, for architectures >>>> that can support 8, 16 and 32-bit data - targets with 36 bit cpus, for >>>> example, will always be problematic for portable code). >>> >>> >>> For what purposes would you want an integer type of a given >>> size (other than an integer type of *at least* a given size)? >> >> When you want perform modulo-N arithmetic. > > Hmm.. don't the low-order N bits of an unsigned always obey modulo-N > arithmetic?
Until divide or shift right. -- Grant Edwards grante Yow! This is my WILLIAM at BENDIX memorial CORNER visi.com where I worship William Bendix like a GOD!!
Martin Wells wrote:

> You can be fully portable and efficient at the same time.
Then why is the method you propose completely unportable?
> #if VALUE_BITS(char unsigned) == N
I've informed you days ago that such a VALUE_BITS functionality doesn't exist.
John Devereux wrote:
> Hmm.. don't the low-order N bits of an unsigned always obey modulo-N > arithmetic? I.e, use the "guaranteed long enough" type then mask at > the point of use.
I'm sure you'll be prepared to show the world how to mask modulo 2^32 arithmetic, given that pre-C99 standard C doesn't offer any way to express 2^32 as a numeric constant?
Hans-Bernhard Br=F6ker:

> Martin Wells wrote: > > You can be fully portable and efficient at the same time. > > Then why is the method you propose completely unportable?
It's not non-portable.
> > #if VALUE_BITS(char unsigned) =3D=3D N > > I've informed you days ago that such a VALUE_BITS functionality doesn't > exist.
Indeed you did misinform me of such. I've already posted the VALUE_BITS macro. I could fill a warehouse with the things that you don't know. Maybe you should consider the possibility that just because you don't know how to do something, that doesn't mean that someone else doesn't know how to. Martin
Hans-Bernhard Br=F6ker:

> > Hmm.. don't the low-order N bits of an unsigned always obey modulo-N > > arithmetic? I.e, use the "guaranteed long enough" type then mask at > > the point of use. > > I'm sure you'll be prepared to show the world how to mask modulo 2^32 > arithmetic, given that pre-C99 standard C doesn't offer any way to > express 2^32 as a numeric constant?
It's easy to get only the bits you want: (Unchecked, likely to contain an error or two) #define BITMASK_X_BITS_SET(one_expression,x) ( \ ( \ ( \ ( \ (one_expression) << (x-1) \ ) \ \ -1 \ ) \ \ << 1 \ ) \ \ & 1 ) #define GET_LOWER_X_BITS(val,x) ((val) & BITMASK_X_BITS_SET((val)*0+1,x) Martin
Hans-Bernhard Br&ouml;ker <HBBroeker@t-online.de> writes:

> John Devereux wrote: >> Hmm.. don't the low-order N bits of an unsigned always obey modulo-N >> arithmetic? I.e, use the "guaranteed long enough" type then mask at >> the point of use. > > I'm sure you'll be prepared to show the world how to mask modulo 2^32 > arithmetic, given that pre-C99 standard C doesn't offer any way to > express 2^32 as a numeric constant?
unsigned long x; ... x &= 0xffffffff; -- John Devereux
On Sat, 13 Oct 2007 11:36:13 -0700, Martin Wells wrote:

> It's not non-portable.
The example you showed relied on interpreting types during macro processing. No compiler following the C standard has to do that. This trick is non-portable.
> I could fill a warehouse with the things that you don't know. > Maybe you should consider the possibility that just because you don't > know how to do something, that doesn't mean that someone else doesn't > know how to.
Before saying such things one should be very careful (apart of being not really polite): it could be just the other way around. Rob
rob:

> > It's not non-portable. > > The example you showed relied on interpreting types during macro > processing. No compiler following the C standard has to do that. > This trick is non-portable.
Wups you're right, I forgot the preprocessor can't play with type casts and so forth. Looks like we'll have to use limits.h: #if UCHAR_MAX > ...
> > I could fill a warehouse with the things that you don't know. > > Maybe you should consider the possibility that just because you don't > > know how to do something, that doesn't mean that someone else doesn't > > know how to. > > Before saying such things one should be very careful (apart of being not > really polite): it could be just the other way around.
When I'm unsure of something, or just plain ignorant of something, I don't declare my thoughts as explicit truth -- I'll let be known that I'm not 100% sure on what I'm saying. Contrast the two: 1) There's no way of getting VALUE_BITS 2) I don't know of any way of getting VALUE_BITS, does anyone else? Martin
Martin Wells wrote:
> David: > >> That is why the <stdint.h> types >> were defined, and that is why they are important if you want portable >> code that works on a wide range of targets (at least, for architectures >> that can support 8, 16 and 32-bit data - targets with 36 bit cpus, for >> example, will always be problematic for portable code). > > > For what purposes would you want an integer type of a given size > (other than an integer type of *at least* a given size)? The only > difference between a 33-Bit int and a 32-Bit int is that the former > will take longer to wrap around to zero upon overflow, and it will > also retain an extra bit when left-shifted. You'll still have all the > range you want though. > > Martin >
There are several situations where a 33-bit integer would not suit when I want a 32-bit integer (or more realistically, reasons why I might particularly want a 16-bit integer and not a 32-bit integer). Here's a few of them: 1) RAM space - on a small micro, you don't want to waste space. 2) Speed - on a small micro, larger integers take a lot more time and code space to work with. 3) Interfaces with hardware - you want to get the sizes matching exactly. 4) Interfaces with external equipment or other programs - if you are sending data to another program, you want to be 100% sure of the data formats. 5) Bit manipulation - sometimes it's important to know the exact number of bits when doing logic operations. 6) Array efficiency - it is often more efficient to access arrays of structs if the element size is a power of two for easy calculation of addresses, so it's important to know the exact size of the elements. There are probably many more reasons, but that's enough to get started. mvh., David

The 2024 Embedded Online Conference