Toaster
Toaster

Reputation: 93

C Enum Warnings

I'm updating a physics simulation C code to use enums from long lists of #defines, but have run into an odd bug. A structure contains an enum as:

enum spec_mod_type_enum 
{ SPEC_MOD_PL=1, 
  SPEC_MOD_EXP=2,
} spec_mod_type[NXBANDS];

(NXBANDS is just a #defined value)

Due to an oversight, no key is added for -1 whilst in another file, it's modified as:

xplasma->spec_mod_type[n] = -1;

However, when compiled in both clang and gcc this results in a silent failure; the value is set to undefined, rather than -1, with unpleasant consequences. This is odd as:

  1. I was under the impression enums could be set to values outside their range.

  2. We get no warnings about this with -Wall (or -Wextra), when it seems like the exact thing enums are supposed to warn over.

Could anyone enlighten me as to why this might be happening? And/or which compiler flags would warn us about this, or at least change the default behaviour for enums to allow this set?

Upvotes: 3

Views: 1537

Answers (2)

Ben
Ben

Reputation: 2942

I see your issue. I think it is initialized to an undefined value -1 before it gets set to another enum value, right? I would recommend to add another enum value SPEC_MOD_UNDEFINED. Then you can simply initialize it to that at first and then set to another one later.

Also if you want to iterate over all enum values, it is practical to add a NUM_SPEC_MOD at the end, which will then take a number one higher than the last specified before.

Then you can do a

for(int i = SPEC_MOD_PL; i < NUM_SPEC_MOD;i++)

over all values. And only assign specific values to the enums if necessary, it automatically does that by itself. But seeing that you modify existing code, I see why you might want to add specific numbers. For my for-example, the numbers have to be rising integer values so that all numbers refer to a certain state.

This works because C exposes the integer representation of enumeration values directly to the programmer. Integers and enum values can be mixed freely, and all arithmetic operations on enum values are permitted. It is even possible for an enum variable to hold an integer that does not represent any of the enumeration values. In fact, according to the language definition, your code will define SPEC_MOD_PL and SPEC_MOD_EXP as constants of type int, which will only be converted (silently) to enum spec_mod_type if they are stored in a variable of that type.

(from Wikipedia Enumerated type article)

Upvotes: 0

Bathsheba
Bathsheba

Reputation: 234685

The behaviour of your program could vary from platform to platform:

The C standard allows the compiler to choose any underlying integral type for the enumerator that's capable of representing all the explicit values given: 1 and 2 in your case.

So a compiler might pick an unsigned type for your enumeration. Assigning a negative value in that case would cause wraparound modulo 2^n where n is the number of bits used to represent the unsigned type.

On the other hand, it might pick a signed type, in which case -1 would be representable.

One remedy would be to introduce a negative dummy value into your enumerator.

Upvotes: 7

Related Questions