Re: Delay Routine: Fully-portable C89 if possible



John Devereux wrote:
David Brown <david@xxxxxxxxxxxxxxxxxxxxxxxxxxxxx> writes:

[...]

Secondly, I was suggesting that if you want portable code, you have to
use size-specific integer types. Using <stdint.h> is an easy way to
get that - otherwise, a common format header file that is adapted for
the compiler/target in question is a useful method. It doesn't really
matter whether you use "uint32_t" from <stdint.h>, or have a "typedef
unsigned long int uint32_t" in a common header file - nor does it
matter if you give the type your own name. But it *does* matter that
you have such types available in your code.

Certainly many of the situations where size specifics are important
are in hardware dependant and non-portable - and thus the only issue
is that the code in question is clear.

But there are many cases where you need a minimum range which may not
be satisfied by "int" on every platform, and also where you want the
fastest implementation. If you have a function
delayMicrosecs(unsigned int n), then the useful range is wildly
different on a 32-bit target and a 16-bit (or 8-bit, with 16-bit int)
target. On the other hand, if it is declared with "uint32_t n", it is
portable from 8-bit to 64-bit processors. Since the OP was asking for
portable code in an embedded newsgroup, there's no way he can make
assumptions about the size of "int".

If I wanted a minimum range of 32 bits, I would use "unsigned
long". As you know this is already guaranteed to be at least 32 bits
on all platforms, so I don't think there is any portability problem
with 8,16 and 32 bit processors.


"unsigned long int" will, as you say, work for when you need at least 32 bits, and "unsigned int" will work for when you need at least 16 bits. I prefer to be more specific and explicit - I find I often want my types to be of a given width, neither more nor less than I specify. I'll grant you that this is somewhat a matter of style - but I am not alone in this (it takes a big demand to get something like <stdint.h> into the standards).

Now I admit that these are the only cases I think about when writing
my own embedded code. But I suppose you could argue that on some
hypothetical 64 bit embedded processor, I would then be using values
that were longer than needed. But,


The 64-bit MIPs processors are non-hypothetical embedded processors (although they are not common in this newsgroup).

- with 64 bit CPUs, is it not true that the compilers still tend to
have 32 bit longs, and use "long long" for 64 bits?


That varies. "long long int" is always at least 64 bits, but there are different models for whether "long int" is 32-bit or 64-bit. In particular, 64-bit Windows uses 32-bit long ints, while 64-bit Linux uses 64-bit long ints. It is also perfectly possible for both "int" and "long int" to be 64-bit, but I think that is uncommon.

- If longs *are* 64 bits, it could be because 32 bit operations are
*slower* on that processor. Strictly, I think there might not even
*be* a 32 bit type - unlikely, I agree.


As you say, possible but unlikely. I don't agree with your thoughts as to why "long int" might be 32-bit or 64-bit - the trouble is, different implementations of the same instruction set might have different balances (the first Intel chips to support amd64 instructions were, IIRC, quite a bit slower at 64-bit arithmetic, while the AMD chips were faster in 64-bit mode).

- On a 64 bit system, it is very likely that I would want to take
advantage of the greater word size and use 64 bit arguments in any
case.


For most of my work, I use 8 and 16 bit systems, but I sometimes use 32-bit cpus (some with 16-bit external buses, making 16-bit ints faster for some purposes) - thus I have the same situation when using 32-bit cpus as you describe for 64-bit cpus.
.