tags:

views:

84

answers:

4

Hello. I'm writing some C code for an embedded application, and I've run into a problem wherein a compare against an enumerated value is not being executed correctly. Take the following code snippet, for example:

typedef unsigned int UINT16;
typedef enum enum_items_tag
{
   ITEM_1,
   ITEM_2,
   ITEM_3,

   /* ... */

   ITEM_918,
   MAX_ENUM_ITEMS
} enum_items_t;

UINT16 n;

for ( n = 0; n < MAX_ENUM_ITEMS; n++ )
{
   // Do something
}

The code executes as expected, until n is incremented to equal MAX_ENUM_ITEMS, at which time the compare fails, and execution continues within the loop (when it should have exited). I've done things like this in the past without any problems.

I've tried re-typing n as enum_items_t (i.e. declaring n as "enum_items_t n"), as well as type casting MAX_ENUM_ITEMS as UINT16. The only other thing I can think of at this point is that maybe there is an issue with the number of items there are in my enumerated type (919). Does anyone know if there are such constraints on enumerated types? I'm using a GCC based compiler. Or, if you have any other ideas, it would be much appreciated. Thanks.

A: 

ISO C is rather vague on internal representation of enums, but one thing it does guarantee is that the type used should be wide enough to handle all values, so long as you don't exceed the limit for int. Unless you're using some compiler switch to enable implementation-specific behavior which sets enum representation to something fixed (like a char).

In any case, try printing out sizeof(enum_items_t) and see what you get.

Also, int should be at least 16 bits wide per ISO C, but on embedded platforms (and especially DSPs) you run into all kinds of weird things, so check if int is really 16-bit, as well.

Pavel Minaev
Sounds not really like the problem as it is not a "round" binary number that causes the trouble. To be honest this sounds to me more like a gcc bug.
jdehaan
+4  A: 

Could it be an off-by-one error? I would expect that gcc starts enums at 0... but you say you saw the value increase to 919 while debugging. So that makes me think either you've got an extra value in the enum by accident or the enum values are 1-based just like the naming scheme implies.

If ITEM_1 == 1 then either start your n at 1... or change the value of MAX_ENUM_ITEMS as follows:

typedef enum enum_items_tag
{
   ITEM_1,
   ITEM_2,
   ITEM_3,

   /* ... */

   ITEM_918,
   MAX_ENUM_ITEMS = ITEM_918
} enum_items_t;
Philip Davis
Good catch. To test, add `ITEM_0` to the enum.
GMan
I'm pretty sure GCC starts enums at 0. I almost believe this is a standard, but I don't have a copy of the standard. It seems like something that would be standardized - it can't have a huge impact on implementations.
Chris Lutz
@Chris: It is in the Standard (6.7.2.2 in n1256.pdf) "3 ... If the first enumerator has no =, the value of its enumeration constant is 0. ..."
pmg
Yep, the offset turned out to be the problem. Good catch!
Jim Fell
A: 

I'd print out MAX_ENUM_ITEMS just to make sure that the value of it is what you think it should be. With a list that long it would not be difficult to messs it up.

DarthNoodles
+1  A: 

Try starting your loop with n = ITEM_1?

Calyth