【问题标题】:Is there a way to make `enum` type to be unsigned?有没有办法让“枚举”类型无符号?
【发布时间】:2010-04-28 18:15:55
【问题描述】:

有没有办法让enum 类型无符号?下面的代码给了我一个关于有符号/无符号比较的警告。

enum EEE {
    X1 = 1
};

int main()
{
    size_t x = 2;
    EEE t = X1;
    if ( t < x ) std::cout << "ok" << std::endl;

    return 0;
}

我试图强制编译器使用以下枚举的无符号基础类型:

enum EEE {
    X1 = 1,
    XN = 18446744073709551615LL
    // I've tried XN = UINT_MAX (in Visual Studio). Same warning.
};

但这仍然会发出警告。


将常量更改为UINT_MAX 使其在 GNU C++ 中按照标准工作。似乎是VS中的一个错误。感谢 James 的提示。

【问题讨论】:

  • @sbi,这不是重复的,因为 C++ 标准给出了关于如何将 undelying 类型更改为 unsigned int 的提示。我正在尝试使用它。
  • @Sbi,下次请复制并粘贴整个 URL。 Stack Overflow 会将其缩写为您发布的内容,但是当您包含整个内容时,我们可以获得显示问题标题(实际上是 URL 的其余部分)的工具提示,而无需访问链接。将您的评论与 James 的评论进行比较。
  • @Rob:你说得对,在这种情况下会更好。我养成了剪掉多余部分的习惯,因为 cmets 的空间有限。

标签: c++ enums


【解决方案1】:

你可以试试:

enum EEE {
    X1 = 1,
    XN = -1ULL
};

没有U,整数文字是有符号的。

(这当然假设您的实现支持long long;我假设它支持,因为原始问题使用LL;否则,您可以使用UL 作为long)。

【讨论】:

  • 这适用于 GNU C++,但不适用于 Visual Studio。似乎是VS中的一个错误。这段代码也是正确的,但最好使用UINT_MAX
  • @James,啊,确实。如果你用“LLU”而不是像我那样只用“U”,它就不能再选择“long”了。绕过“更大”含义的不清楚措辞的好方法!如果您使用限制宏或 -1ULL(或 C++03 中的 -1UL 或 long long 实现),我会赞成:)
  • ULLONG_MAX 在 VC++ 中也不起作用。我认为编译器认为他可以生成 128 位代码。
  • @Johannes:感谢您提醒我有关 -1 技巧的信息;它让我忘记了。
  • @Kirill:无论我给一个枚举器取什么值,在VS2008中枚举总是有四个字节的大小。 :-/
【解决方案2】:

不在当前版本的 C++ 中。 C++0x 将提供强类型枚举。

暂时可以使用if ( static_cast&lt;size_t&gt;(t) &lt; x )去除警告。

【讨论】:

  • 我试图避免额外的static_cast's。
【解决方案3】:

如果你想比较它,你也可以重载运算符

enum EEE {
    X1 = 1
};

bool operator<(EEE e, std::size_t u) {
  return (int)e < (int)u;
}

但是,对于右侧的任何整数类型,您都必须这样做。否则,如果您这样做 e &lt; 2 将是模棱两可的:编译器可以使用您的 operator&lt; 完全匹配左侧但需要在右侧进行转换,或其内置运算符需要提升左侧并匹配正确的一面。

所以最终,我会提出以下版本:

/* everything "shorter" than "int" uses either int or unsigned */
bool operator<(EEE e, int u) {
  return (int)e < (int)u;
}

bool operator<(EEE e, unsigned u) {
  return (unsigned int)e < (unsigned int)u;
}


bool operator<(EEE e, long u) {
  return (long)e < (long)u;
}

bool operator<(EEE e, unsigned long u) {
  return (unsigned long)e < (unsigned long)u;
}

/* long long if your compiler has it, too */

不是很好 :) 但至少你列举的用户很容易相处。但是,如果您最终不想与普通的int 比较,而是与一些有意义的值进行比较,我会按照其他人的建议做,并添加另一个具有值2 的枚举器,并命名它。这样,警告也会消失。

【讨论】:

  • 相当冗长,但如果您希望避免使用 static_cast 则可以完成工作
  • -1U?您是否尝试将一元减号运算符应用于无符号类型?那应该将类型更改为签名吗?
  • @Kirill,它将保持unsigned,但会将其值更改为UINT_MAX。所以你不需要限制标头。
  • 我用UINT_MAX 删除了“技巧”,因为我认为“更大”实际上意味着“sizeof”值——如“类型大小”(在询问 dgregor 之后)。 “long”可能与“unsigned int”的大小相同,因此它仍然可以选择“long”。唯一安全的方法似乎是使用@James 解决方案并使用-1ULL,如果您想在没有强制转换和运算符重载等情况下使用枚举。
  • -1ULL 看起来很有希望,但在 Visual Studio 中它也不起作用。我会尝试在 VS 错误跟踪器中发布错误。
【解决方案4】:

根据Are C++ enums signed or unsigned? 你的编译器可以选择枚举是否有符号,尽管有一些 cmets 说在 C++0x 中你可以指定它是无符号的。

【讨论】:

    【解决方案5】:

    C++ Enumeration Declarations on MSDN:

    enum EEE : unsigned {
        X1 = 1 
    }; 
    

    【讨论】:

    • @KirillV.Lyadvinsky:真的吗?它应该。 MSVC 说它从 MSVC2005 开始编译这个。
    • 我在参考文献中搜索了 unsigned,但它并没有像您在上面提供的那样显示。 unsigned 在一个句子中只使用一次。你确定这个引用是正确的吗?
    • @jww 好吧,这句话解释了它应该如何使用。对type 的引用是对文章顶部的示意图声明的引用:enum [tag] [: type] ... 所以说type 可以有任何标量有符号或无符号整数类型。这应该确实有效。它在 VS 2010 上为我编译,但它给出警告 C4480(使用了非标准扩展:为枚举指定底层类型)。
    【解决方案6】:

    为什么不

    enum EEE {
        X1 = 1,
        x = 2 // pick more descriptive name, a'course
    };
    

    if ( size_t( t ) < x )
    

    【讨论】:

    • 你怎么知道你的枚举 EEE 的枚举值是无符号的?在我看来,它们就像整数。
    • @chollida,最终目标是摆脱警告,而不是让它未签名,我怀疑。他的方式确实做到了。
    • @cohollida:问题是如何使枚举类型无符号。这意味着他不会输入负值,或者如果他这样做了,他想要模算术。
    猜你喜欢
    • 1970-01-01
    • 2016-07-24
    • 2013-10-27
    • 2015-06-07
    • 2011-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多