C++ 枚举是有符号的还是无符号的?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/159034/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Are C++ enums signed or unsigned?
提问by Matt
Are C++ enums signed or unsigned? And by extension is it safe to validate an input by checking that it is <= your max value, and leave out >= your min value (assuming you started at 0 and incremented by 1)?
C++ 枚举是有符号的还是无符号的?通过扩展,通过检查输入是 <= 您的最大值,并忽略 >= 您的最小值(假设您从 0 开始并以 1 递增)来验证输入是否安全?
采纳答案by zvrba
You shouldn't rely on any specific representation. Read the following link. Also, the standard says that it is implementation-defined which integral type is used as the underlying type for an enum, except that it shall not be larger than int, unless some value cannot fit into int or an unsigned int.
你不应该依赖任何特定的表示。阅读以下链接。此外,该标准表示,它是实现定义的,哪种整数类型用作枚举的基础类型,但它不应大于 int,除非某些值不能放入 int 或无符号 int。
In short: you cannot rely on an enum being either signed or unsigned.
简而言之:您不能依赖有符号或无符号的枚举。
回答by Michael Burr
Let's go to the source. Here's what the C++03 standard (ISO/IEC 14882:2003) document says in 7.2-5 (Enumeration declarations):
让我们回到源头。以下是 C++03 标准 (ISO/IEC 14882:2003) 文档在 7.2-5(枚举声明)中的说明:
The underlying type of an enumeration is an integral type that can represent all the enumerator values defined in the enumeration. It is implementation-defined which integral type is used as the underlying type for an enumeration except that the underlying type shall not be larger than int unless the value of an enumerator cannot fit in an int or unsigned int.
枚举的基础类型是可以表示枚举中定义的所有枚举器值的整数类型。使用哪种整数类型作为枚举的基础类型是实现定义的,除非基础类型不得大于 int,除非枚举数的值不能适合 int 或 unsigned int。
In short, your compiler gets to choose (obviously, if you have negative numbers for some of your ennumeration values, it'll be signed).
简而言之,您的编译器可以选择(显然,如果您的某些枚举值有负数,则它将被签名)。
回答by Adam Rosenfield
You shouldn't depend on them being signed or unsigned. If you want to make them explicitly signed or unsigned, you can use the following:
您不应该依赖于它们是否已签名或未签名。如果要使它们显式签名或未签名,可以使用以下命令:
enum X : signed int { ... }; // signed enum
enum Y : unsigned int { ... }; // unsigned enum
回答by Matt
You shouldn't rely on it being either signed or unsigned. According to the standard it is implementation-defined which integral type is used as the underlying type for an enum. In most implementations, though, it is a signed integer.
你不应该依赖它是签名的还是未签名的。根据标准,实现定义了哪种整数类型用作枚举的基础类型。但是,在大多数实现中,它是一个有符号整数。
In C++0x strongly typed enumerationswill be added which will allow you to specify the type of an enum such as:
在 C++0x中将添加强类型枚举,这将允许您指定枚举的类型,例如:
enum X : signed int { ... }; // signed enum
enum Y : unsigned int { ... }; // unsigned enum
Even now, though, some simple validation can be achieved by using the enum as a variable or parameter type like this:
尽管如此,即使是现在,也可以通过将枚举用作变量或参数类型来实现一些简单的验证,如下所示:
enum Fruit { Apple, Banana };
enum Fruit fruitVariable = Banana; // Okay, Banana is a member of the Fruit enum
fruitVariable = 1; // Error, 1 is not a member of enum Fruit
// even though it has the same value as banana.
回答by JavaMan
Even some old answers got 44 upvotes, I tend to disagree with all of them. In short, I don't think we should care about the underlying type
of the enum.
即使是一些旧的答案也得到了 44 票,我倾向于不同意所有这些答案。简而言之,我认为我们不应该关心underlying type
枚举的。
First off, C++03 Enum type is a distinct type of its own having no concept of sign. Since from C++03 standard dcl.enum
首先,C++03 Enum 类型是一种独特的类型,没有符号概念。从 C++03 标准开始dcl.enum
7.2 Enumeration declarations
5 Each enumeration defines a type that is different from all other types....
So when we are talking about the sign of an enum type, say when comparing 2 enum operands using the <
operator, we are actually talking about implicitly converting the enum type to some integral type. It is the sign of this integral type that matters. And when converting enum to integral type, this statement applies:
因此,当我们谈论枚举类型的符号时,比如使用<
运算符比较 2 个枚举操作数时,我们实际上是在谈论将枚举类型隐式转换为某种整数类型。重要的是这种积分类型的符号。将 enum 转换为整型时,此语句适用:
9 The value of an enumerator or an object of an enumeration type is converted to an integer by integral promotion (4.5).
And, apparently, the underlying type of the enum get nothing to do with the Integral Promotion. Since the standard defines Integral Promotion like this:
而且,显然,枚举的基础类型与 Integral Promotion 无关。由于标准定义了 Integral Promotion 是这样的:
4.5 Integral promotions conv.prom
.. An rvalue of an enumeration type (7.2) can be converted to an rvalue of the first of the following types that can represent all the values of the enumeration
(i.e. the values in the range bmin to bmax as described in 7.2: int, unsigned int, long, or unsigned long.
So, whether an enum type becomes signed int
or unsigned int
depends on whether signed int
can contain all the values of the defined enumerators, not the underlying type of the enum.
因此,枚举类型是否成为signed int
或unsigned int
取决于是否signed int
可以包含定义的枚举器的所有值,而不是枚举的基础类型。
See my related question Sign of C++ Enum Type Incorrect After Converting to Integral Type
请参阅我的相关问题 Sign of C++ Enum Type Incorrect After Converting to Integral Type
回答by Cristián Romo
The compiler can decide whether or not enums are signed or unsigned.
编译器可以决定枚举是有符号还是无符号。
Another method of validating enums is to use the enum itself as a variable type. For example:
验证枚举的另一种方法是使用枚举本身作为变量类型。例如:
enum Fruit
{
Apple = 0,
Banana,
Pineapple,
Orange,
Kumquat
};
enum Fruit fruitVariable = Banana; // Okay, Banana is a member of the Fruit enum
fruitVariable = 1; // Error, 1 is not a member of enum Fruit even though it has the same value as banana.
回答by Kris Kumler
In the future, with C++0x, strongly typed enumerationswill be available and have several advantages (such as type-safety, explicit underlying types, or explicit scoping). With that you could be better assured of the sign of the type.
将来,在 C++0x 中,强类型枚举将可用并具有多个优点(例如类型安全、显式底层类型或显式范围)。这样您就可以更好地确定类型的符号。
回答by Steve Jessop
In addition to what others have already said about signed/unsigned, here's what the standard says about the range of an enumerated type:
除了其他人已经说过的关于有符号/无符号的内容之外,以下是标准关于枚举类型范围的内容:
7.2(6): "For an enumeration where e(min) is the smallest enumerator and e(max) is the largest, the values of the enumeration are the values of the underlying type in the range b(min) to b(max), where b(min) and b(max) are, respectively, the smallest and largest values of the smallest bitfield that can store e(min) and e(max). It is possible to define an enumeration that has values not defined by any of its enumerators."
7.2(6): "对于 e(min) 是最小的枚举数,e(max) 是最大的枚举,枚举的值是 b(min) 到 b(max) 范围内的基础类型的值),其中 b(min) 和 b(max) 分别是可以存储 e(min) 和 e(max) 的最小位域的最小值和最大值。可以定义具有未定义值的枚举由其任何枚举器。”
So for example:
例如:
enum { A = 1, B = 4};
defines an enumerated type where e(min) is 1 and e(max) is 4. If the underlying type is signed int, then the smallest required bitfield has 4 bits, and if ints in your implementation are two's complement then the valid range of the enum is -8 to 7. If the underlying type is unsigned, then it has 3 bits and the range is 0 to 7. Check your compiler documentation if you care (for example if you want to cast integral values other than enumerators to the enumerated type, then you need to know whether the value is in the range of the enumeration or not - if not the resulting enum value is unspecified).
定义枚举类型,其中 e(min) 为 1,e(max) 为 4。如果基础类型是有符号 int,则所需的最小位域有 4 位,如果您的实现中的 int 是二进制补码,则有效范围为枚举是 -8 到 7。如果基础类型是无符号的,那么它有 3 位,范围是 0 到 7。如果您关心,请检查您的编译器文档(例如,如果您想将除枚举数以外的整数值转换为枚举类型,那么您需要知道该值是否在枚举范围内 - 如果不是,则结果枚举值未指定)。
Whether those values are valid input to your function may be a different issue from whether they are valid values of the enumerated type. Your checking code is probably worried about the former rather than the latter, and so in this example should at least be checking >=A and <=B.
这些值是否是您函数的有效输入可能与它们是否是枚举类型的有效值不同。您的检查代码可能担心前者而不是后者,因此在此示例中至少应该检查 >=A 和 <=B。