55

我知道如果我像这样定义一个枚举工作日:

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

然后,默认情况下,MON 在内部等于 0,TUE 为 1,WED 为 2...

但如果我这样定义:

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

然后两者都MONTUE得到 0 的值。

系统如何在内部区分 MON 和 TUE?我的意思是,如果我声明这样的内容:

enum weekday today = 0;

那么是今天MON还是TUE?或者,从哲学上讲,两者兼而有之?

4

5 回答 5

84

C 枚举是“真正的”整数——不仅因为它们碰巧以这种方式实现,还因为标准枚举类型定义为具有整数值。所以 的值today是“真的” 0。所发生的只是你为值 0 创建了两个不同的名称。

我想“今天是周一还是周二”的答案是“是”;-)

该语言不会阻止您,因为有时枚举具有相同值的多个名称很有用。例如:

enum compression_method {
    COMP_NONE = 0,
    COMP_LOW = 1,
    COMP_HIGH = 2,
    COMP_BEST = 2,
    COMP_FASTEST = 0,
};
于 2012-07-10T11:46:27.420 回答
22

为什么两个不同的枚举常数可以具有相同的整数值?

因为N1265 C99 标准草案在 6.7.2.2/3 "Enumeration specifiers" 明确允许它:

使用枚举器 with=可能会产生枚举常量,其值与同一枚举中的其他值重复。

系统如何在内部区分 MON 和 TUE?

我认为这是不可能的,因为它们是编译时常量(6.6/6“常量表达式”)。因此,他们:

  • 编译后无法修改以使它们不同

  • 没有地址可以区分它们:C 中枚举值的内存位置

    编译时间常数不需要任何地址,因为地址对于您无法修改的东西是无用的。

GCC 只是在编译时用汇编中的立即值替换枚举成员的使用。考虑:

#include <stdio.h>

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;
}

使用 GCC 4.8 x86_64 编译和反编译:

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

输出包含:

    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 <main+0x32>
                    2e: R_X86_64_PC32       i-0x4
  32:       89 c6                   mov    %eax,%esi

所以我们看到:

  • 枚举成员用作立即$0x1234数,因此无法知道它们来自哪里
  • 然而,变量i来自内存0x0(%rip)(要重新定位),因此可以通过地址区分两个变量
于 2015-06-18T13:15:49.887 回答
13

只是为了补充其他答案,我会给你一个实际的例子,说明如何对给定的不同枚举使用相同的值enum是非常有用的:

enum slots_t {
    SLOT_FIRST = 0,
    SLOT_LEFTARM = SLOT_FIRST,
    SLOT_RIGHTARM = 1,
    SLOT_TORSO = 2,
    SLOT_LEFTLEG = 3,
    SLOT_RIGHTLEG = 4,
    SLOT_LAST = SLOT_RIGHTLEG
};

然后你可以在你的代码中做:

for (int i = SLOT_FIRST; i <= SLOT_LAST; ++i) { }
于 2015-06-18T17:59:09.453 回答
8

它与哲学(或不是)一样

#define ZILCH 0
#define NADA  0

在许多用途中,不同的名称产生相同的数字是有意义的。

于 2014-06-16T11:02:28.420 回答
2

枚举常量的名称用于分配值,而不是实际值本身。如果将值 0 分配给今天,则输出值将为 0。是的,MON 和 TUE 的值都为 0,其余的值将分配为 WED=1 THU=2,依此类推。

于 2012-07-10T12:02:17.623 回答