Why can two different enum enumeration-constants have the same integer value?

前端 未结 5 1159
半阙折子戏
半阙折子戏 2021-01-31 14:08

I know that if I defined an enum weekday like this:

enum weekday {
    MON,
    TUE,
    WED,
    THU,
    FRI,
};

Then, MON would internally e

5条回答
  •  北恋
    北恋 (楼主)
    2021-01-31 14:49

    Why can two different enumeration-constants have the same integer value?

    Because it is explicitly allowed by the N1265 C99 standard draft at 6.7.2.2/3 "Enumeration specifiers":

    The use of enumerators with = may produce enumeration constants with values that duplicate other values in the same enumeration.

    How would a system differentiate MON and TUE internally?

    I think it is impossible because they are compile time constants (6.6/6 "Constant expressions"). As a consequence they:

    • cannot be modified to make them differ after compilation

    • have no address to tell them apart: Memory location of enum value in C

      Compile time constants don't need any address because addresses are useless for things which you cannot modify.

    GCC simply replaces the usage of enum members with immediate values in assembly at compile time. Consider:

    #include 
    
    enum E {
        E0 = 0x1234,
        E1 = 0x1234
    };
    int i = 0x5678;
    
    int main() {
        printf("%d\n", E0);
        printf("%d\n", E1);
        printf("%d\n", i);
        return 0;
    }
    

    Compile and decompile with GCC 4.8 x86_64:

    gcc -c -g -O0 -std=c89 main.c
    objdump -Sr main.o
    

    The output contains:

        printf("%d\n", E0);
       4:       be 34 12 00 00          mov    $0x1234,%esi
      ...
        printf("%d\n", E1);
      18:       be 34 12 00 00          mov    $0x1234,%esi
      ...
        printf("%d\n", i);
      2c:       8b 05 00 00 00 00       mov    0x0(%rip),%eax        # 32 
                        2e: R_X86_64_PC32       i-0x4
      32:       89 c6                   mov    %eax,%esi
    

    So we see that:

    • the enum members are used as immediates $0x1234, so it is impossible to know where they came from
    • the variable i however comes from memory 0x0(%rip) (to be relocated), so two variables could be differentiated by address

提交回复
热议问题