C + + 枚举是有符号的还是无符号的?

C + + 枚举是有符号的还是无符号的?通过扩展验证输入是否安全,可以检查输入是否 < = 您的最大值,并省略 > = 您的最小值(假设您从0开始并递增1) ?

96721 次浏览

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.

你不应该依赖任何具体的代表。阅读下面的 链接。此外,该标准还说,它是实现定义的,其中整数类型被用作枚举的基础类型,除非某个值不能适合于 int 或无符号 int,否则它不应该大于 int。

简而言之: 您不能依赖于枚举是有符号的还是无符号的。

你不应该指望它们是签名的还是没签名的。如果要使它们显式签名或无签名,可以使用以下方法:

enum X : signed int { ... };    // signed enum
enum Y : unsigned int { ... };  // unsigned enum

在将来,使用 C + + 0x,强类型枚举将可用,并且具有几个优点(例如类型安全、显式底层类型或显式作用域)。这样你就可以更好地确定类型的符号。

让我们回到源代码,下面是 C + + 03标准(ISO/IEC 14882:2003)文档在7.2 -5(枚举声明)中所说的:

枚举的基础类型 is an integral type that can represent 中定义的所有枚举数值 列举。它是 实现-定义哪个积分 类型用作基础类型 除了 基础型号不得较大 除非 枚举数不能适合整型或 无符号整数。

简而言之,您的编译器可以选择(显然,如果您的某些枚举值为负数,那么它将是有符号的)。

你不应该指望它被签署或未签署。根据标准,它是实现-定义了哪个整型被用作枚举的底层类型。但是,在大多数实现中,它是一个有符号整数。

在 C + + 0x 中,将添加 强类型枚举,这将允许您指定枚举的类型,如:

enum X : signed int { ... };    // signed enum
enum Y : unsigned int { ... };  // unsigned enum

不过,即使是现在,也可以通过使用枚举作为变量或参数类型来实现一些简单的验证,如下所示:

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.

除了其他人已经说过的有符号/无符号之外,下面是标准对枚举类型范围的说明:

7.2(6) : “对于 e (min)是最小枚举数,e (max)是最大的枚举数,枚举数的值是 b (min)到 b (max)范围内的底层类型的值,其中 b (min)和 b (max)分别是能存储 e (min)和 e (max)的最小位字段的最小和最大值。可以定义一个枚举,它的值不是由其任何枚举器定义的。”

例如:

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).

这些值是否是函数的有效输入与它们是否是枚举类型的有效值可能是不同的问题。您的检查代码可能会担心前者,而不是后者,因此在本例中至少应该检查 > = A 和 < = B。

即使一些老的答案得到了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

7.2 Enumeration declarations
5 Each enumeration defines a type that is different from all other types....

因此,当我们讨论一个枚举类型的符号时,比如当使用 <运算符比较两个枚举操作数时,我们实际上是在讨论隐式地将枚举类型转换为某种整数类型。It is the sign of this integral type that matters.在将枚举转换为整数类型时,应用下面的语句:

9 The value of an enumerator or an object of an enumeration type is converted to an integer by integral promotion (4.5).

而且,显然,枚举的基础类型与积分升级没有任何关系。因为标准是这样定义整体推广的:

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.

因此,枚举类型是否成为 signed intunsigned int取决于 signed int是否可以包含所定义的枚举器的所有值,而不是枚举的底层类型。

看我的相关问题 转换为整数类型后 C + + 枚举类型符号不正确

虽然上面的一些答案可以说是正确的,但它们没有回答我的实际问题。编译器(gcc9.3.0)发出以下警告:

enum FOO_STATUS {
STATUS_ERROR = (1 << 31)
};

该警告是在使用时发出的:

unsigned status = foo_status_get();
if (STATUS_ERROR == status) {

(除了这个代码是不正确的... 不要问。)

当正确询问时,编译器不会发出错误。

enum FOO_STATUS {
STATUS_ERROR = (1U << 31)
};

注意,1U使表达式为无符号的。