Re: Integer types in embedded systems
- From: Jack Klein <jackklein@xxxxxxxxxxx>
- Date: Fri, 02 May 2008 22:53:42 -0500
On Fri, 2 May 2008 13:42:23 -0700 (PDT), Tomás Ó hÉilidhe
<toe@xxxxxxxxxxx> wrote in comp.lang.c:
Let's say we had a simple function for returning the amount of days in
a month:
unsigned DaysInMonth(unsigned const month)
First, omitting the "int", even if legal, is sloppy and would not
survive a code inspection in a professional organization.
Second, applying a const qualifier to a value parameter might pass a
code inspection, but is considered by many to be just plain prissy.
{
switch (month)
{
case 8:
case 3:
case 5:
case 10: return 30;
case 1: return 28;
default: return 31;
}
}
Notice the integer type I've used, i.e. "unsigned int" rather than
"unsigned char" or "unsigned short".
Many of the microcontrollers (i.e. a small chip that has a CPU and
RAM, basically it's a tiny little computer) in use nowadays do
arithmetic on 8-Bit numbers.
An example of a prevalent microcontroller nowadays would be the
PIC16F684. It's only got about 35 different CPU instructions. All of
the arithmetic instructions work on 8-Bit registers.
We won't get into many people's opinions about PICs, it would be
off-topic here.
In my little code snippet above, the biggest number used is 31, which
of course would fit inside an "unsigned char".
Which would, in C, immediately be promoted to either signed or
unsigned int. So you'd gain nothing. Some, perhaps many, embedded
compilers for 8-bit micros have an option for telling the compiler not
to promote 8-bit values. Once you do that, it's not really C anymore.
In C, the plain "int" type is described as the "natural" type for the
system. I think a lot of people agree that this is the type you use
when you "just want to store a number", and I think a lot of people
expect it to be the fastest integer type.
You seem to be a beginning embedded programmer, particularly based on
some of the posts you've made on comp.arch.embedded. On the other
hand, you make these opinionated statements like "a lot of people
expect". Who are these people? How do you know what they expect?
I think that no experienced embedded programmer would expect that. I
think anyone who hasn't learned not to expect that does not have the
experience to professionally program embedded systems. And on
anything outside the embedded arena these days, they can get away with
expecting that.
Most C programmers these days are woefully ignorant, and they expect
many things, such as...
--a char is signed and has a range of [-128,127]
--an int is four bytes
--a pointer is four bytes
--a float is four bytes
--there is a stack
....an I could go on and on.
The only problem with int, however, is that it must be at least 16-
Bit.
Actually, that's not a problem. That's a guarantee and a good one.
On an 8-Bit microcontroller such as the PIC16F684, this of course
means that int will NOT be the most efficient type. The problem with
Actually, it generally is the most efficient type if you need a type
that can hold an object in either of the ranges [-32767,32767] or
[0,65535].
this however is that we have code snippets like the one above that
think they're using the best integer types for the job. If we were to
Your assumption is that they think that. Have you asked "they" what
they think, or are you just assuming?
re-write the code for an embedded system, we'd probably have:
Actually, speaking for more than 25 years of embedded system
development, I'd say they would most likely not rewrite the code,
Knuth being absolutely correct about premature optimization. Once the
program was finished and meeting its requirements, but needed a
performance boost, then it might possible be rewritten as you suggest
below. But only after a profiler or other hard measurement tool
proved that it was a bottleneck.
char unsigned DaysInMonth(char unsigned const month)
{
Really, lose the const, it just makes you look silly.
As does your insistence on putting the base type before the unsigned
qualifier. At least as important as portability, and more important
in many cases in the real world, is maintainability. While your code
might be perfectly valid and legal to the compiler, not one C
programmer in a 1000 writes code like that.
Your writing code contrary to the common idiom just because you like
the way it looks is nothing but a cause for confusion, causing others
to take longer to read and understand your code for inspection or
maintenance. If it survived code inspection, which I think not likely
in most quality shops, embedded or otherwise.
switch (month)
But remember, at this point, C requires that the unsigned char be
promoted to either an int or unsigned int anyway.
{
case 8:
And the type of the 8, and the rest of the constants in your cases
already have type int.
case 3:
case 5:
case 10: return 30;
case 1: return 28;
default: return 31;
}
}
I'd like now to bring up the topic of portable programming. In my own
code, I've begun to use types such as:
uint_fast8_t
Does that mean that you don't use 'char', 'int', 'long', etc.?
Basically I'm saying "I want the fastest integer type whose range is
at least up to 255".
Basically, you are fooling yourself if you are feeding this code to a
conforming C compiler, because it must perform the standard
promotions. If you are operating something that is not quite a
conforming C compiler, perhaps by using certain invocation options,
that's a different story, but also rather off-topic here.
In this way, I can write code that will peform optimally on both
embedded systems and PC's.
Again, if the compiler you feed this to is instructed to compile in
conforming mode, this code will be basically the same as the original
version.
To people out there who are enthusiastic about writing portable code,
do you think it's time we started using types like uint_fast8_t
instead of "unsigned int"?
Actually, I haven't had a use for the fast types yet. I have used the
(u)int_leastx_t types, for portability between DSPs where CHAR_BIT is
larger than 8, and "ordinary" platforms where CHAR_BIT is exactly 8.
In fact I've successfully written code that had to pack and unpack
binary communications packets using unit_least8_t that compiles
unchanged on CHAR_BIT 8 and CHAR_BIT 16 implementations.
Of course, even if our target platform doesn't supply an stdint.h, we
can always have a default version of it, e.g.:
typedef char unsigned uint_fast8_t;
or:
typedef unsigned uint_fast8_t;
There have been plenty of examples on the web of stdint.h files for
compilers that do not supply them. At least one was written by a
member of the C standard committee. I've written quite a few myself
for older embedded compilers. And I've written one for Visual C++ 6,
which I often use for testing algorithms.
The real issue here is premature micro optimization. The majority of
the posters and readers in this group, as opposed to
comp.arch.embedded, are not embedded system programmers. They have,
and probably will never have, a need to port their code to anything
smaller than a 32-bit processor. Your advice is not relevant to them.
In my opinion, you are worrying about efficiency under the guise of
portability. If you are really concerned with portability, understand
that portability to other programmers is as important as portability
to other implementations and platforms.
Get rid of "char unsigned const" and write "const unsigned char" like
all the other C programmers do. Save your creativity for clever
algorithms, and write the simplest and clearest code to implement the
algorithm correctly.
And at the very end, when your program works and meets all of its
requirements, then you can look at optimizations like this. But only
if this is the code causing one of the bottle necks.
For example, if this code is executed once per day when the clock
rolls over from 23:59:50 to 0:00:00, to decide whether to change the
month and date, or just the date, on a display, what have you gained
by saving 5 or 50 clock cycles out every 24 hours?
--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
.
- Follow-Ups:
- Re: Integer types in embedded systems
- From: Nick Keighley
- Re: Integer types in embedded systems
- From: Tomás Ó hÉilidhe
- Re: Integer types in embedded systems
- From: Thad Smith
- Re: Integer types in embedded systems
- References:
- Integer types in embedded systems
- From: Tomás Ó hÉilidhe
- Integer types in embedded systems
- Prev by Date: Re: doubly-linked list & sorting
- Next by Date: Re: trying to find the error
- Previous by thread: Re: Integer types in embedded systems
- Next by thread: Re: Integer types in embedded systems
- Index(es):
Relevant Pages
|