2

I am reading some codes and I found this _BIG_ENUM=0xFFFFFFFF in the last value of the enum.what is the correct meaning of this line. And this _BIG_ENUM is not used anywhere in the code;

#define CLS_COMM_CONFIG PORT_0,BAUD_9600,DATA_BIT_8,ONE_STOP,NO_FLOW_CONTROL
#define PLS_COMM_CONFIG PORT_1,BAUD_115200,DATA_BIT_8,ONE_STOP,NO_FLOW_CONTROL

typedef enum _comm_config
{

 _Zero=0,
 PORT_0=_Zero,
 BAUD_2400=_Zero,
 NONE=_Zero,
 HALF_STOP=_Zero,
 DATA_BIT_5=_Zero,
 NO_FLOW_CONTROL=_Zero,

 _One = 1,
 PORT_1=_One,
 BAUD_4800=_One,
 ODD=_One,
 ONE_STOP=_One,
 DATA_BIT_6=_One,

 _Two=2,
 PORT_2=_Two,
 BAUD_9600=_Two,
 EVEN=_Two,
 TWO_STOP=_Two,
 DATA_BIT_7=_Two,

 _Three=3,
 PORT_3=_Three,
 BAUD_19200=_Three,
 DATA_BIT_8=_Three,

 _Four=5,
 PORT_5=_Four,
 BAUD_115200=_Four,
 DATA_BIT_9=_Four,

 _BIG_ENUM=0xFFFFFFFF,

}COMMConfig;
voidpointer
  • 301
  • 1
  • 8
  • Please don't radically change the question once there are answers posted. I did a rollback of your changes. – Lundin Oct 17 '19 at 08:11
  • Actually why does the question title say one thing and the code another thing? ... – Lundin Oct 17 '19 at 08:18
  • Note also the `_BIG_ENUM` is a reserved identifier per [**7.1.3 Reserved identifiers**, paragraph 1 of the C standard](https://port70.net/~nsz/c/c11/n1570.html#7.1.3): "All identifiers that begin with an underscore and either an uppercase letter or another underscore are always reserved for any use." As a reserved identifier, its use is improper. – Andrew Henle Oct 17 '19 at 09:17

2 Answers2

5

It doesn't make any sense and is a bug.

I suppose the programmer didn't quite know how enums work and thought they could enforce enums to become 32 bit by assigning a large integer constant to one of the enumeration constants. This is true, but they picked a bad value which won't work as they thought it would.

The problem is that while enumeration variables may have implementation-defined sizes, enumeration constants such as _BIG_ENUM are always of type int 1).

But 0xFFFFFFFF won't fit in a 32 bit int so this is a bug. The hex constant 0xFFFFFFFF is actually of type unsigned int (assuming 32 bit) and it won't fit, so there will be an implementation-defined conversion from signed to unsigned. Meaning we end up with the value -1 on 2's complement systems. Although gcc and clang with strict standard settings even refuse to compile the code when the enumeration constant is given an integer constant larger than INT_MAX.

When faced with an enumeration constant of value -1, the compiler is free to pick any signed type2) for enumeration variables of that type, not necessarily a 32 bit one.

The code can be fixed by changing it to _BIG_ENUM=INT_MAX, (limits.h). Then the enumerated type will either become int or unsigned int.


1) C17 6.7.2.2/1

The expression that defines the value of an enumeration constant shall be an integer constant expression that has a value representable as an int.

2) C16 6.7.2.2/4

Each enumerated type shall be compatible with char, a signed integer type, or an unsigned integer type. The choice of type is implementation-defined,128) but shall be capable of representing the values of all the members of the enumeration.

128) An implementation may delay the choice of which integer type until all enumeration constants have been seen.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • 1
    Reading in detail and this in particular _1453 108) An implementation may delay the choice of which integer type until all enumeration constants have been seen._ means that the compiler could choose `unsigned int` apparently. Although I understand your point, it appears that it's possible that with some compiler this trick was working fine. But we don't know whether this code compiled with a specific compiler or not. – Iharob Al Asimi Oct 17 '19 at 07:48
  • @IharobAlAsimi No it cannot because the enumeration constant `_BIG_ENUM` is assigned the value -1. – Lundin Oct 17 '19 at 07:50
  • Re "*But 0xFFFFFFFF won't fit in a 32 bit int*", Indeed. [Unsigned hexadecimal constant in C?](https://stackoverflow.com/q/4737798/589924) – ikegami Oct 17 '19 at 07:50
  • @Iharob Al Asimi, You're confusing the type of the `enum` (which is flexible) and the type of the expression that defines the value of the constant (which isn't). – ikegami Oct 17 '19 at 07:52
  • 3
    @ikegami Yes, the original code will not compile with strict settings on gcc because of that bug. – Lundin Oct 17 '19 at 07:52
  • @ikegami That's exactly what is happening to me. You are both right. I wouldn't have thought of ever doing such a thing, but I attempted to understand the situation from the standard and got confused with that exactly. Thanks for clarifying. – Iharob Al Asimi Oct 17 '19 at 07:55
  • BTW gcc's error message is pretty clear about the fact that the problem is the value of the constant. You need `-pedantic` though. I do use `-pedantic` regularly. – Iharob Al Asimi Oct 17 '19 at 07:56
3

Some compilers can optimize enum to smaller word-sizes, but this could cause problem with interoperability when not all of the code is compiled with the same compiler.

If an enum is assigned a 32-bit value this optimization is prevented, forcing this enum to be encoded as a 32 bit integer.

Simson
  • 3,373
  • 2
  • 24
  • 38
  • 1
    Why did anyone downvote this? It's a fine answer and I suspect it is correct. – Iharob Al Asimi Oct 17 '19 at 07:38
  • This is wrong since 0xFFFFFFFF won't fit inside an enumeration constant. Enumeration constants are always `int` and can't get different sizes, unlike enumeration variables. – Lundin Oct 17 '19 at 07:38
  • @Lundin, Why do you say 0xFFFFFFFF doesn't fit in a (32-bit) `int`? – ikegami Oct 17 '19 at 07:40
  • 1
    @Lundin check this https://embedded.fm/blog/2016/6/28/how-big-is-an-enum and this http://c0x.coding-guidelines.com/6.7.2.2.html precisely the last sentence. – Iharob Al Asimi Oct 17 '19 at 07:41
  • @Iharob Al Asimi, That's not what Lundin is disagreeing with – ikegami Oct 17 '19 at 07:43
  • @Lundin, if I remember correctly this is an issue if you use both RVCT and gcc in the same project – Simson Oct 17 '19 at 07:43
  • @ikegami Actually the comment says that 32bit integers are too large for an enum. The truth is that the compiler might choose smaller integer sizes, apparently never more than 32bit which isn't guaranteed either, the only thing that is 100% sure is that it's maximum `sizeof(int)` but then the post lacks information about whether or not there are tests that ensure this will not cause problems. – Iharob Al Asimi Oct 17 '19 at 07:43
  • @Iharob Al Asimi, No they said `0xFFFFFFFF` doesn't fit in a 32-bit int. Their first comment (on the question itself) is clearer (" But `0xFFFFFFFF` won't fit in a 32 bit int") – ikegami Oct 17 '19 at 07:44
  • An issue with RVCT 3.1, where they apparently had not read @Lundin's post about integer enums http://www.keil.com/support/man/docs/armcc/armcc_chr1360774870320.htm this hack would trick this compiler – Simson Oct 17 '19 at 08:04
  • @Simson From the link: "In strict C, enumerator values must be representable as ints. That is, they must be in the range -2147483648 to +2147483647, inclusive. A warning is issued for out-of-range enumerator values". So Keil appears to behave just as gcc and clang. – Lundin Oct 17 '19 at 08:08
  • "An object of type enum is implemented in the smallest integral type that contains the range of the enum. " - this is what caused this mess - and I totally agree enum-s are nonsense in embedded C. – Simson Oct 17 '19 at 08:15