Search code examples
cenumscomparison

C Compare enumerate with invalid value


I would like try to understand how is working the compilator when we compare an enumerate with invalid value, and what the program is doing during execution.

I found strange source code during my work, and did not understand the behaviour of the program, which was not giving me the expected result.

I wrote the following little program to summarize my problem.

I create an enum E_Number and I instanciate a variable a, with the value -1. Then I perform comparison on a to check if it belongs to the range of the enum.

(I know, this is really strange, but this is exactly what i found in source code !)

I expected the result tells me Not in range because of the fail of the first condition (a >= FIRST_ENUM). But it was the fail of the second condition (a < NB_MAX_NUMBER) which gave me the right result (see the printf())...

If I cast a in (int) in the if conditions, I get excepted results.

So what is happening during the execution ? Is the program considering -1 as an other possible enum value which will be positionned after NB_MAX_NUMBER ? What is the rule for > and < operator on enum ?

#include <stdio.h>

#define FIRST_ENUM 0
typedef enum{
    NUM_1 = FIRST_ENUM, 
    NUM_2, 
    NUM_3,
    NB_MAX_NUMBER
}E_Number; 

int main()
{
    E_Number a = -1; 

    if ((a >= FIRST_ENUM) && (a < NB_MAX_NUMBER))
    {
        printf("In Range\n"); 
    }
    else
    {
        printf("Not in Range\n"); 
    }

    printf("1st condition = %s\n", (a >= FIRST_ENUM)?"TRUE":"FALSE"); 
    printf("2nd condition = %s\n", (a < NB_MAX_NUMBER)?"TRUE":"FALSE"); 

    return 0; 
}

gcc program.c

.\a.exe
Not in Range
1st condition = TRUE
2nd condition = FALSE

I am working with MINGW compilator ( gcc (x86_64-win32-seh-rev1, Built by MinGW-W64 project) 4.9.2 )


Solution

  • Quote from ISO/IEC 9899:1999, 6.7.2.2p3

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

    So, when you declare an enumeration, you cannot be sure a priori about what kind of data will the implementation of C choose to store that variable. Optimisation reasons, the compiler may not choose an integer type on 4 bytes if you store enumeration constants between [-128, +127]. The implementation may choose char to store an enumerated variable, but you cannot be sure. Any integer data type can be chosen as time as it can store all possible values.