C语言中默认的枚举值在所有编译器中都是相同的吗?

121

当像下面展示的那样声明一个枚举时,所有C编译器在Linux和Windows系统上默认会将值设置为 x=0y=1z=2 吗?

typedef enum {
    x,
    y,
    z
} someName;

3
需要遵守标准,我确定有人能够引用它们。 - Nemo
4个回答

130

是的。除非在枚举的定义中另有说明,否则初始枚举值总是为零,并且每个后续枚举器的值都比前一个枚举器大一。


15
在C和C++中都需要相同的行为。在C++中,这是通过[dcl.enum]实现的:“如果第一个枚举值没有初始化程序,则相应常量的值为零。没有初始化器的枚举器定义通过将上一个枚举器的值增加一来给枚举器赋值。” - Ben Voigt
3
是的,还有其他以字母C开头的语言,比如C#。 - James McNellis

75

C99标准

N1265 C99 draft 在6.7.2.2/3 "枚举说明符"中指出:

带有=的枚举器将其枚举常量定义为常量表达式的值。如果第一个枚举器没有=,则其枚举常量的值为0。每个后续没有=的枚举器将其枚举常量定义为前一个枚举常量的值加1得到的常量表达式的值。(使用具有=的枚举器可能会产生枚举常量的值,这些值重复了同一枚举中的其他值。)

因此,在符合规范的实现中,始终成立以下内容:

main.c

#include <assert.h>
#include <limits.h>

enum E {
    E0,
    E1,
    E2 = 3,
    E3 = 3,
    E4,
    E5 = INT_MAX,
#if 0
    /* error: overflow in enumeration values */
    E6,
#endif
};

int main(void) {
    /* If unspecified, the first is 0. */
    assert(E0 == 0);
    assert(E1 == 1);
    /* Repeated number, no problem. */
    assert(E2 == 3);
    assert(E3 == 3);
    /* Continue from the last one. */
    assert(E4 == 4);
    assert(E5 == INT_MAX);
    return 0;
}

编译并运行:

gcc -std=c99 -Wall -Wextra -pedantic -o main.out main.c
./main.out

在Ubuntu 16.04,GCC 6.4.0中测试通过。


8
如果枚举变量的第一个值未初始化,则C编译器会自动将其赋值为0。编译器会不断增加前面枚举变量的值1。
例如:
enum months{jan,feb,mar}

解释: jan的值将为0,feb的值将为1,mar的值将为2。

enum months{jan=123,feb=999,mar}

解释: jan的值将为123,feb的值将为999,mar的值将为1000。

enum months{jan='a',feb='s',mar}

解释: jan的值将会是“a”,feb的值将会是“s”,mar的值将会是“t”。


3
“mar being 't'” 并不能保证其一定是字母表顺序中的下一个字母,因为可能存在某些字符集,其中字母并非按照字母表顺序依次排列。 - M.M

-18

是的,枚举值默认从0开始到第n个元素适用于任何平台。


17
请考虑您的回答如何为答案库做出贡献。也就是说,您的新回答(5年后)如何添加一些新的内容,而其他回答没有涵盖到?乍一看,它似乎比其他两个答案更少提供信息。 - LawfulEvil
3
嗯,@LawfulEvil,请放心。多个答案可以让未来查看此内容的人获得多个视角。话虽如此,这是一个格式不良、信息不足的答案,但本身丰富的答案并不是坏事。 - Kenny Worden

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接