为了好奇,我正在试验这个:
enum RxqType
{
A = (1 << 0),
B = (1 << 1),
C = (A | B),
D = A+B+C
};
枚举器C和D是根据早期的枚举器定义的。这很不寻常,所以我不确定它是否安全。我通过谷歌找不到任何关于它的例子(可能会忽略)。
在Visual C ++ 2013和MinGW上printf
或cout
C
和D
似乎没问题。但我担心它是否符合标准,是否会触发未定义的行为。
任何人都可以回答我对标准一致性和未定义行为的担忧吗?还有什么我需要关注的吗?
答案 0 :(得分:21)
enum RxqType
{
A = (1 << 0),
B = (1 << 1),
C = (A | B),
D = A+B+C
};
在C和C ++中,这是有效的。
对于C:
(C11,6.2.1p7)“每个枚举常量的范围都是在枚举器列表中出现其定义枚举器之后开始的。”
对于C ++:
(C ++ 11,3.3.2p4)“枚举器的声明点紧跟在枚举器定义之后。”
答案 1 :(得分:5)
是的,这在C99标准部分草案6.2.1
标识符范围中有所说明,它告诉我们每个枚举数在定义后都在范围内:
每个枚举常量都有范围 在枚举器列表中出现其定义的枚举器之后就开始了。
C ++标准草案3.3.2
声明要点中涵盖了这一点,其中包括:
宣言的要点 对于枚举,紧接在其枚举说明符(7.2)或其第一个中的标识符(如果有)之后 opaque-enum-declaration(7.2),以先到者为准。
为了完整起见,我们可以转到C99标准草案的6.7.2.2
枚举说明符部分,它告诉我们一个枚举器可以由一个常量表达式设置,一个枚举器本身就是一个不断表达。
enumerator:
enumeration-constant
enumeration-constant = constant-expression
6.6
常量表达式部分涵盖了什么是常量表达式,它告诉我们枚举数是常量,而且整数常量的算术表达式也是常量表达式。
答案 2 :(得分:1)
虽然已经注意到它完全有效,但有一点需要注意:在定义枚举类型时,在C ++中,已经声明的枚举器可能没有您确切的类型。期待。结果,像
enum E {
a = INT_MAX,
b = UINT_MAX,
c = a + 1, // error: overflow
};
无效,即使这是:
enum E {
a = INT_MAX,
b = UINT_MAX,
};
enum E2 {
c = a + 1, // okay: a is promoted to unsigned int
};
对于类似的示例,重载决策可能不像您期望的那样:
char f(int);
template <typename T>
char (&f(T))[2];
enum E {
a = 0,
b = sizeof(f(a)), // 1
};
enum E2 {
c = sizeof(f(a)), // 2
};
还有其他类似的例子有点不直观。
对于C,规则稍微简单一些。在C中,枚举常量的类型独立于枚举类型,因此a + 1
的示例即使使用E2
也无效。这确实导致了一致的结果。
答案 3 :(得分:-3)
是的,100%有效。事实上,这很好,感激不尽。
enum RxqType
{
A = (1 << 0),
B = (1 << 1),
C = (A | B),
D = A+B+C
};