Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overflow of an enum type in C?

If I have an enum type, like:

enum week{ sunday=0, monday, tuesday, wednesday, thursday, friday, saturday};

and I have:

enum week day;
day = saturday;
day++;

What will be the value of day?

like image 802
jnd Avatar asked May 23 '15 03:05

jnd


3 Answers

An enumerated type is essentially a named integral value. That enumerated type is associated with an underlying integral type that can represent all the named values. That underlying integral type is required to be able to represent all the unique named values, but its actual type is implementation defined.

In this case, the numeric value of saturday will be 6. Incrementing it will give the numeric value of 7. In practice, that is unlikely to overflow the underlying integral type (int, char, unsigned char, or whatever the compiler chooses), so printing the value using the %d format will print 7.

However, there is no enumerated (named) value of type enum week with a value of 7.

If incrementing an enumerated value would overflow the underlying integral type (which is not the case here) the result is undefined. This is because the underlying integral type may be signed or unsigned, and overflowing a signed integral type gives undefined behaviour.

Theoretically, it is possible that a compiler may use an underlying type for enum week that can only represent the values 0 to 6 - in which case incrementing saturday gives undefined behaviour. In practice, AFAIK, there has yet to be any C compiler which does not choose an underlying type to be one of the standard integral types (char, int, unsigned char, unsigned, etc). All of those types can represent the numeric value of 7.

like image 67
Peter Avatar answered Sep 30 '22 17:09

Peter


I was only able to find a draft of the C89 specification, and I'm no C expert, so I might be misunderstanding it. But its section 3.5.2.2 says that

The identifiers in an enumerator list are declared as constants that have type int and may appear wherever such are permitted. [...] Each enumerated type shall be compatible with an integer type.

I think that means that day++ will always yield 7 here (one more than the value represented by saturday).

like image 20
fzzfzzfzz Avatar answered Sep 30 '22 19:09

fzzfzzfzz


Given:

enum week {
    sunday=0, monday, tuesday, wednesday, thursday, friday, saturday
};
enum week day = saturday;
day ++;

the value of day is 7.

Quoting the 2011 ISO C standard, 6.7.2.2 paragraph 1:

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

_Bool is an unsigned integer type, but it doesn't meet the requirements for this particular enumeration type.

Since the value of CHAR_BIT is required to be at least 8, and the types char, unsigned char, and signed char are required to have no padding bits, the range of each of the character types must cover at least 0 through 127. Wider integer types (short, int, etc.) have ranges at least as wide as that of signed char or unsigned char. Therefore the implementation-defined type that is compatible with enum week must have a lower bound no greater than 0, and an upper bound no less than 127.

(WARNING: Language-lawyering follows.) There might be a loophole that allows for extended integer types with a wider range than _Bool but a narrower range than char. For example, I think an extended integer type with a size of 8 bits but only 3 value bits would be legal. But since integer types are required to use a binary representation, an unsigned type with 3 value bits would be able to represent values from 0 to 7, and an unsigned type with 2 value bits would not be able to represent the value of saturday. Since an enum week can hold the value 6, it must also be able to hold the value 7. In an unusual implementation it might not be able to represent the value 8, but you're unlikely encounter such an implementation.

Basically, given the requirement that integer types use a pure binary representation, any type that can represent 6 can also represent 7, though it doesn't automatically follow that it can also represent 8.

like image 36
Keith Thompson Avatar answered Sep 30 '22 17:09

Keith Thompson