是C ++枚举符号或无符号?

问题描述 投票:102回答:9

是C ++枚举符号或无符号?并通过扩展它安全通过检查,这是验证输入<=你的最大价值,并留下了> =您的最小值(假设你开始在0和1递增)?

c++ enums
9个回答
58
投票

你不应该依赖于任何特定的表示。阅读下面的link。此外,标准的说,这是实现定义其积分型被用作基础类型的枚举,除了它应不大于INT时,除非某些值不能装配到int或一个unsigned int。

总之:你可以不依赖于枚举是有符号或无符号。


98
投票

让我们去到源。下面介绍一下C ++标准03(ISO / IEC 14882:2003)文档中7.2-5(枚举声明)说:

基础类型枚举的是,可以表示所有在枚举所定义的枚举值的整数类型。它是实现定义其积分型被用作基础类型的枚举不同的是,除非一个枚举的值不能在int或unsigned int适合的基本类型不得大于INT大。

总之,你的编译器就可以选择(当然,如果你有负数为你的一些ennumeration值,它会签署)。


20
投票

你不应该依赖于它们被带符号。如果你想使他们明确符号或无符号,你可以使用以下命令:

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

15
投票

你不应该依赖于它被符号或无符号。根据标准它是实现定义其积分型被用作基础类型的枚举。在大多数实现,但是,它是一个符号整数。

C ++ 0x中strongly typed enumerations将被添加,这将允许用户指定一个枚举如的类型:

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.

5
投票

编译器可以决定枚举无论是否带符号。

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

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.

5
投票

即使是一些老的答案有44个upvotes,我倾向于与他们不同意。总之,我不认为我们应该关心的枚举的underlying type

首先,C ++ 03 Enum类型是不具有符号的概念的不同类型它自己的。由于从C ++ 03标准dcl.enum

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

所以,当我们在谈论一个枚举类型的标志,说比较使用<运营商,我们实际上是在谈论隐式枚举类型转换为某种整型2个枚举操作数时。这是一个重要的这种整体式的标志。并转换枚举整型的时候,这句话适用于:

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是否可以包含所定义的枚举,而不是基本的类型枚举的所有的值。

见我相关的问题Sign of C++ Enum Type Incorrect After Converting to Integral Type


4
投票

在未来,随着的C ++ 0x,strongly typed enumerations将可用,并且具有几个优点(如类型安全,明确的基础类型,或显式作用域)。这样,您可以更好地保证类型的符号。


4
投票

除了别人已经说过符号/无符号,这里就是标准说,大约一个枚举类型的范围:

7.2(6):“对于一个枚举其中e(分钟)是最小的枚举和e(最大值)是最大的,枚举的值在范围B(分钟)至b的基本类型的值(最大),其中b(分钟)和b(最大)分别是可以存储E(分钟)和e(最大值)最小的位域的最小值和最大值,这是可能的,以限定具有未定义值的枚举其任何统计员“。

因此,例如:

enum { A = 1, B = 4};

定义枚举类型,其中e(分钟)为1和e(max)是4.如果底层类型符号整数,则最小的所需位字段具有4个位,并且如果在您的实施int为二的补码,则有效范围枚举为-8〜7。如果底层类型是unsigned,那么它有3位,范围为0〜7。检查你的编译器的文档,如果你关心(例如,如果你想比统计员的投积分值等枚举类型,那么你需要知道的价值是否在枚举与否的范围 - 如果不是导致枚举值是不确定的)。

无论这些值是有效的输入您的功能可能是从他们是否是枚举类型的有效值一个不同的问题。您的检查代码是可能担心前者而非后者,因此,在这个例子中,至少应该检查> = A和<= B。


0
投票

std::is_signed<std::underlying_type +检查范围的枚举默认int

https://en.cppreference.com/w/cpp/language/enum意味着:

main.cpp中

#include <cassert>
#include <iostream>
#include <type_traits>

enum Unscoped {};
enum class ScopedDefault {};
enum class ScopedExplicit : long {};

int main() {
    // Implementation defined, let's find out.
    std::cout << std::is_signed<std::underlying_type<Unscoped>>() << std::endl;

    // Guaranteed. Scoped defaults to int.
    assert((std::is_same<std::underlying_type<ScopedDefault>::type, int>()));

    // Guaranteed. We set it ourselves.
    assert((std::is_same<std::underlying_type<ScopedExplicit>::type, long>()));
}

GitHub upstream

编译并运行:

g++ -std=c++17 -Wall -Wextra -pedantic-errors -o main main.cpp
./main

输出:

0

经测试在Ubuntu 16.04,GCC 6.4.0。

© www.soinside.com 2019 - 2024. All rights reserved.