Specify size of enum?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Specify size of enum?

19,654 Views
LethalCorpse
Contributor I

I'm using codewarrior 10 for the MC9S08SH8. I've got a union producing an issue which took a while to track down, and stems from the size of an enum. The size of an enum is compiler-specific and should default to the smallest integral type which is large enough to fit all of the values, but not larger than int. In this case, it seems the sizeof enum is fixed at 16-bit. For starters, that wastes a heck of a lot of memory if you use a boolean typedef (which I do). The real problem was caused by this code:

 

typedef enum { SOME_COMMAND=0x00, ...        SOME_OTHER_COMMAND=0x0F } Commandt;typedef union{ UINT8 s[4]; struct {
                Commandt command;  UINT16 address;  UINT8 data; } l;} Packet;

 I expected this to allow me to write the raw bytes and then efficiently access the contents, but of course the CMD_Commandt overlapped the high byte of the address and broke the code. I've managed to correct the issue with the type sizes options in the build settings, but it's not exactly portable code.

 

 

Is there a #pragma option to set the size of an enum, or better yet, some way to force it to always use the smallest number of whole bytes for an enum?

 

I'd really like it to be able to use the smallest number of bits for an enum, and hence stack multiple boolean variables in a bitfield, but I suspect that's a bridge too far :smileyhappy:.

Labels (1)
Tags (1)
0 Kudos
6 Replies

7,868 Views
bigmac
Specialist III

Hello,


LethalCorpse wrote:

...

I'd really like it to be able to use the smallest number of bits for an enum, and hence stack multiple boolean variables in a bitfield, but I suspect that's a bridge too far :smileyhappy:.

 


If the requirement is simply to handle single bit flags in a memory efficient, and code efficient manner, there is an alternative approach is to directly utilize a bit field.  With single-bit elements, I do not anticipate portability issues.  But maybe others will disagree.

 

Using CW, this method appears to work as anticipated, for both 8-bit and 16-bit variables.  For code efficiency on 8-bit MCUs, the variable should be placed in zero page RAM.

 

Within a "common.h" header file, the generic bit fields are defined for both 8-bit and 16-bit types.

 

// File: common.h...// Single bit flags:union FLAGSTR8 {   byte B;   struct {      unsigned flag0     :1;      unsigned flag1     :1;      unsigned flag2     :1;      unsigned flag3     :1;      unsigned flag4     :1;      unsigned flag5     :1;      unsigned flag6     :1;      unsigned flag7     :1;   } b;};typedef union FLAGSTR8 FLAGSTR8_;union FLAGSTR16 {   word W;   struct {      unsigned flag0     :1;      unsigned flag1     :1;      unsigned flag2     :1;      unsigned flag3     :1;      unsigned flag4     :1;      unsigned flag5     :1;      unsigned flag6     :1;      unsigned flag7     :1;      unsigned flag8     :1;      unsigned flag9     :1;      unsigned flag10    :1;      unsigned flag11    :1;      unsigned flag12    :1;      unsigned flag13    :1;      unsigned flag14    :1;      unsigned flag15    :1;   } b;};typedef union FLAGSTR16 FLAGSTR16_;

 

Then within a specific .c file, the zero page variable is defined.

 

#include "common.h"// Global/static variables:#pragma DATA_SEG __SHORT_SEG MY_ZEROPAGEvolatile FLAGSTR16_ flag;             // Single bit control flags...#pragma DATA_SEG DEFAULT

 

The corresponding .h header file would then #define the bit usage for the variable.  The following example is from one of my projects.  Of course, this approach is based on that used by CW to define the various bits of the hardware registers.

 

#include "common.h"/***********************************************************************/// Global variables:#pragma DATA_SEG __SHORT_SEG MY_ZEROPAGEextern volatile FLAGSTR16_ flag;      // Single bit control flags...#pragma DATA_SEG DEFAULT/***********************************************************************/// Single bit flags:#define flag_COMMAND   flag.b.flag1   // Local command entry mode#define flag_NEWLINE   flag.b.flag2   // New line flag for command entry#define flag_LO_BATT   flag.b.flag3   // Low battery state#define flag_NO_REC    flag.b.flag4   // No record for client code#define flag_WAC_MODE  flag.b.flag5   // Paging message format control#define flag_TSYS      flag.b.flag6   // System timeout flag#define flag_PROMPT    flag.b.flag7   // Previous prompt character#define flag_NORM_S100 flag.b.flag8   // System 100 normal mode#define flag_DFLTPAGE  flag.b.flag9   // Default paging mode flag#define flag_EVPROC    flag.b.flag10  // Default paging event in progress#define flag_DOWNLOAD  flag.b.flag11  // Download mode is current

 

Regards,

Mac

 

0 Kudos

7,868 Views
Lundin
Senior Contributor IV

The size of an enum is indeed implementation-defined by the C standard, but practically it is almost always the same as the size of an int. Instead, use this portable version:

 

enum {
 SOME_COMMAND=0x00,
 ...
  SOME_OTHER_COMMAND=0x0F
};

typedef UINT8 Commandt;


C doesn't have strong typing anyhow, so the above code is identical to yours, as long as it ain't compiled in C++.

 

Also note that both the union and the struct in your code may have additional padding bytes, so they may not be portable either, depending on how you use them.

0 Kudos

7,868 Views
AndersJ
Contributor IV

I want a structure containg the data type Commandt, as described in the original posting.

Using the data type in the structure makes it easy to see what data is allowed

just by looking at the typedef of the data type. The original posters problem remains however,

in that twice as much memory as allocated compared to if the enum is only  one byte.

(Provided of course that only up to 255 individual values are used).

 

How can I use the data type to emphasize the type used,

and STILL  make sure only 1 byte is allocated in the structure, instead of an entire integer?

 

Anders J

 

 

0 Kudos

7,867 Views
BlackNight
NXP Employee
NXP Employee

The Freescale HCS08 compiler has an option to change the size of an enum: e.g. -TE1ue sets enumeration to 8bit unsigned.

 

BK

0 Kudos

7,867 Views
Lundin
Senior Contributor IV

It's a very bad idea to fiddle around with Codwarrior type settings to make your program work. Instead, write portable programs that work on any C compiler.

 

That way you will also become a better C programmer, rather than a better specific-compiler-programmer.

0 Kudos

7,867 Views
djsimpson
Contributor III

The -TE1ue option forces ALL the enums to be 8 bit. It would be nice if the compiler could choose the size based on the maximum enumeration value.

 

My (very) old Introl Compiler for the HC11 automatically did that, and porting the code over has caused a few issues with ENUM. Enums made debugging much easier, as the debugger showed the meaningful enum name.

 

David

 

0 Kudos