Re: Delay Routine: Fully-portable C89 if possible
- From: David Brown <david@xxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
- Date: Mon, 15 Oct 2007 14:41:08 +0200
John Devereux wrote:
David Brown <david@xxxxxxxxxxxxxxxxxxxxxxxxxxxxx> writes:
John Devereux wrote:David Brown <david@xxxxxxxxxxxxxxxxxxxxxxxxxxxxx> writes:
[...]
But a "short int" may be bigger than 16-bit. Some 8-bit compilers mayThere are several situations where a 33-bit integer would not suitI would use "short" for this.
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.
may also implement "short int" as 8-bit - I know it's non-conforming,
but it's far more likely that an embedded programmer will meet a
non-standard compiler with 8-bit shorts than a standard compiler with
36-bit ints.
If a "short" is bigger that 16 bit, surely the int_least16_t will be
too? They both have the same rationale AFAIK.
Yes, I think that's true. But if the target/compiler does not support a true 16-bit int, then I the type "int16_t" would not exist (even though int_least16_t and int_fast16_t would).
Note that it is perfectly possible, though somewhat unlikely in this contrived example, for an embedded compiler to support 16-bit integers while having short ints bigger than 16 bits. Embedded compilers sometimes support different sized types as extensions, beyond what is available through char, short int, int, long int and long long int. It's more realistic to expect sizes such as 24-bit or 40-bit integers to be available in this way, but some compilers have 32-bit short ints (perhaps having 64-bit ints, or perhaps just because 32-bit data are much faster on the architecture in question), and may provide 16-bit integers through an extension.
[...]
extern void sendChar(char c);5) Bit manipulation - sometimes it's important to know the exactMaybe - but I can't think of a real-life example.
number of bits when doing logic operations.
void sendHexNibble(uint8_t n) {
static const char hexChars[] = "0123456789abcdef";
sendChar(hexChars[n]);
}
void sendHexByte(uint8_t n) {
sendHexNibble(n >> 4);
sendHexNibble(n & 0xf);
}
If the uint8_t used by sendHexByte had extra non-zero bits, you would
end up reading outside the hexChars[] array.
I confess, I would probably just go ahead with the exact same code but
using unsigned char as a synonym for uint8_t. They are always the same
on the machines I am familiar with. (And if they were not, there would
probably not be a uint8_t at all!)
I hope you don't have to try to get code working on one of these horrible 16-bit DSPs that can't access 8-bit data directly - an unsigned char is 16 bits on such architectures. I'd rather have the compiler reject the code because there is no uint8_t implemented, than generate incorrect code because I'd assumed a char is 8 bits.
It's perfectly portable - as long as you use size-specific types. And6) Array efficiency - it is often more efficient to access arrays ofYou mean padding the struct with extra elements, or adjusting the type
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.
of existing ones, to bring the total struct size to a power-of-two
number of bytes? I have never thought of doing this, but it sounds
very unportable. I suppose it could avoid doing a multiply on lookup.
yes, it avoids multiplies on lookups - multiplies can be costly on
small cpus. Even on big cpus, avoiding multiplies can be beneficial - sometimes multiplies have longer latencies than shifts, and many have
addressing modes that can include shifts in a single instruction. The
other advantage is that you can be sure that accesses are aligned.
The compiler should pad the struct to ensure that accesses are
possible, but not necessarily optimal - if you know the exact sizes,
you can add padding yourself to choose a balance between space and
speed.
Aren't compilers free to pad structures how they like?
Yes, and they are allowed to generate all sorts of code as long as the visible results are the same. The padding will (normally!) follow specific rules according to alignment rules on the target, but it's certainly advisable to check that the padding is as you expect. I generally have the "-Wpadding" flag on my gcc compiles, so that I get a warning if my structs are unexpectedly padded.
.
- References:
- Delay Routine: Fully-portable C89 if possible
- From: Martin Wells
- Re: Delay Routine: Fully-portable C89 if possible
- From: David Brown
- Re: Delay Routine: Fully-portable C89 if possible
- From: Martin Wells
- Re: Delay Routine: Fully-portable C89 if possible
- From: John Devereux
- Re: Delay Routine: Fully-portable C89 if possible
- From: David Brown
- Re: Delay Routine: Fully-portable C89 if possible
- From: CBFalconer
- Re: Delay Routine: Fully-portable C89 if possible
- From: David Brown
- Re: Delay Routine: Fully-portable C89 if possible
- From: Martin Wells
- Re: Delay Routine: Fully-portable C89 if possible
- From: David Brown
- Re: Delay Routine: Fully-portable C89 if possible
- From: John Devereux
- Re: Delay Routine: Fully-portable C89 if possible
- From: David Brown
- Re: Delay Routine: Fully-portable C89 if possible
- From: John Devereux
- Delay Routine: Fully-portable C89 if possible
- Prev by Date: Re: Delay Routine: Fully-portable C89 if possible
- Next by Date: Re: Sine wave generation
- Previous by thread: Re: Delay Routine: Fully-portable C89 if possible
- Next by thread: Re: Delay Routine: Fully-portable C89 if possible
- Index(es):
Relevant Pages
|