8 bit enum, in C

16.3k views Asked by At

I have to store instructions, commands that I will be receiving via serial. The commands will be 8 bits long.

I need to preserve transparency between command name, and its value. So as to avoid having to translate an 8-bit number received in serial into any type.

I'd like to use Enumerations to deal with them in my code. Only a enumeration corresponds to a on this platform a 16 bit integer.

The platform is AVR ATmega169V microcontroller, on the Butterfly demo board. It is a 8bit system with some limited support for 16bit operations. It is not a fast system and has about 1KB of RAM. It doesn't have any luxuries like file I/O, or an operating systems.

So any suggestions as to what type I should be using to store 8-bit commands?
There has got to be something better than a massive header of #defines.

6

There are 6 answers

2
Michael Foukarakis On BEST ANSWER

gcc's -fshort-enums might be useful:

Allocate to an "enum" type only as many bytes as it needs for the declared range of possible values. Specifically, the "enum" type will be equivalent to the smallest integer type which has enough room.

In fact, here's a page with a lot of relevant information. I hope you come across many GCC switches you never knew existed. ;)

2
Keith Randall On

I don't see why an enum wouldn't work. Comparisons to, and assignments from, an enum should all work fine with the default widening. Just be careful that your 8 bit values are signed correctly (I would think you would want unsigned extension).

You will get 16-bit comparisons this way, I hope that won't be a performance problem (it shouldn't be, especially if your processor is 16-bit as it sounds like it is).

4
Jed Smith On

Microsoft's C compiler allows you to do something like this, but it's an extension (it's standard in C++0x):

enum Foo : unsigned char {
    blah = 0,
    blargh = 1
};

Since you tagged GCC, I'm not entirely sure if the same thing is possible, but GCC might have an extension in gnu99 mode or something for it. Give it a whirl.

1
Roman Nikitchenko On

I'd recommend to stay on enum in any case for the following reasons:

  • This solution allows you to map command values directly to what your serial protocol expects.
  • If you really use 16-bit architecture there is not so big number of advantages to move to 8 bits type. Think about aspects other then 1 memory byte saved.
  • At some compilers I used actual enum size used minimal number of bits (enums that could be fit in byte used only byte, then 16 bit then 32).

First you should not care about real type width. Only if you really need effective way of storage you should use compiler flags such as -fshort-enums on GNU compiler but I don't recommend them unless you really need them.

As last option you can define 'enum' as presentation data for the commands and use conversion to byte with 2 simple operations to store / restore command value to/from memory (and encapsulate this in one place). What about this? These are very simple operations so you can even inline them (but this allows you to really use only 1 byte for storage and from other side to perform operations using most usable enum defined as you like.

0
AnT stands with Russia On

You are trying to solve a problem that does not exist.

Your question is tagged C. In C language enum types in value context are fully compatible with integral types and behave just like other integral types. When used in expressions, they are subjected to exactly the same integral promotions as other integral types. Once you take that into account, you should realize that if you want to store values described by enumeration constants in a 8-bit integral type, all you have to do is to choose a suitable generic 8-bit integral type (say int8_t) and use it instead of enum type. You'll lose absolutely nothing by storing your enum constant values in an object of type int8_t (as opposed to an object explicitly declared with enum type).

The issue you describe would exist in C++, where enum types are separated much farther from other integral types. In C++ using an integral type in place of enum type for the purpose of saving memory is more difficult (although possible). But not in C, where it requires no additional effort whatsoever.

0
Morinho On

Answer which is relevant for ARC compiler (Quoted from DesignWare MetaWare C/C++ Programmer’s Guide for ARC; section 11.2.9.2)

Size of Enumerations The size of an enum type depends on the status of toggle *Long_enums*.

■ If toggle *Long_enums* is off, the enum type maps to the smallest of one, two, or four bytes, such that all values can be represented.

■ If toggle *Long_enums* is on, an enum maps to four bytes (matching the AT&T Portable C Compiler convention).