是C++;枚举是有符号的还是无符号的? 是C++枚举签名还是未签名?此外,通过检查输入是否等于您的最小值(假设您从0开始并递增1),验证输入是否安全?

是C++;枚举是有符号的还是无符号的? 是C++枚举签名还是未签名?此外,通过检查输入是否等于您的最小值(假设您从0开始并递增1),验证输入是否安全?,c++,enums,C++,Enums,编译器可以决定枚举是有符号的还是无符号的 验证枚举的另一种方法是将枚举本身用作变量类型。例如: 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 no

编译器可以决定枚举是有符号的还是无符号的

验证枚举的另一种方法是将枚举本身用作变量类型。例如:

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.
enum { A = 1, B = 4};

你不应该依赖任何具体的表述。阅读以下内容。此外,该标准还规定,实现定义了使用哪个整数类型作为枚举的基础类型,但该类型不得大于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(枚举声明)中所述内容:

枚举的基础类型 是可以表示 中定义的所有枚举数值 枚举。它是 实现定义了哪个积分 类型用作基础类型 对于枚举,但 基础类型不应更大 小于int,除非 枚举数不能放入整数或整数 无符号整数


简而言之,编译器可以进行选择(显然,如果某些ennumeration值为负数,它将被签名)。

您不应该依赖于它是有符号的还是无符号的。根据该标准,实现定义了使用哪个整数类型作为枚举的基础类型。不过,在大多数实现中,它是一个有符号整数

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

除了其他人已经说过的关于有符号/无符号的内容外,以下是标准中关于枚举类型范围的内容:

7.2(6):“对于e(min)是最小枚举数且e(max)是最大枚举数的枚举,枚举的值是在b(min)到b(max)范围内的基础类型的值,其中b(min)和b(max)分别是可存储e(min)和e(max)的最小位字段的最小值和最大值。可以定义具有任何枚举数未定义的值的枚举。“

例如:

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.
enum { A = 1, B = 4};
定义枚举类型,其中e(最小值)为1,e(最大值)为4。如果基础类型是signed int,则所需的最小位字段有4位,如果实现中的int是2的补码,则枚举的有效范围为-8到7。如果基础类型是无符号的,则它有3位,范围为0到7。如果需要,请查看编译器文档(例如,如果要将枚举数以外的整数值强制转换为枚举类型,则需要知道该值是否在枚举范围内-如果不在枚举范围内,则结果枚举值未指定)


这些值是否为函数的有效输入可能与它们是否为枚举类型的有效值不同。您的检查代码可能担心前者而不是后者,因此在本例中,至少应该检查>=A和即使一些旧答案获得44票,我倾向于不同意所有答案。简而言之,我认为我们不应该关心枚举的
底层类型

首先,C++03枚举类型本身是一种独特的类型,没有符号概念。从C++03标准开始
dcl.enum

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

因此,当我们讨论枚举类型的符号时,比如说,当使用
比较两个枚举操作数时,请在未来的C++0x标准中使用
std::is__________签名。@dalle Microsoft编译器也允许类型化枚举。我认为您的第二个示例有点混淆:)(引用了该标准)实际上意味着,如果您将枚举值定义为负数,则可以依赖它进行签名,因为该类型能够“表示枚举中定义的所有枚举数值”。当我们在需要对枚举类型进行签名的上下文中使用枚举类型时,我们实际上是在讨论将枚举隐式转换为整数类型。C++03标准说,这是通过积分提升完成的,与枚举的底层类型无关。所以,我不明白为什么这里的每个答案都提到标准没有定义底层类型?我在这里描述了预期的行为:当您使用
-Wsign conversion
进行编译时,它很重要。我们使用它来帮助捕获代码中的意外错误。但是+1引用了该标准,并指出枚举没有与其关联的类型(
signed
unsigned
),当所有枚举值都是小的正整数时,我们如何避免编译器猜测并告诉它使用基础的unsigned类型?(我们正在捕获一个UBsan查找,因为编译器正在拾取一个int,而int的值会发生溢出。该值是无符号和正的,我们的使用取决于无符号换行以提供减量或“负跨步”)。@jww-我想这将取决于您使用的编译器。由于标准没有规定底层类型,并将其留给实现,因此需要查看工具的文档,看看这个选项是否可行。如果要保证代码中的某种行为,为什么不强制转换表达式中使用的枚举成员?
g++ -std=c++17 -Wall -Wextra -pedantic-errors -o main main.cpp
./main
0