【问题标题】:ENUM constants questionsENUM 常量问题
【发布时间】:2011-09-21 09:02:08
【问题描述】:

已在此站点上发布了如何通过执行以下操作来生成唯一的枚举常量:

enum _EXAMPLE
{
    LEFT = 'left',
    RIGHT = 'right'
    //etc
};

忽略有效性问题,数字是如何产生的?更具体地说,使用什么技术?因为我希望尝试构建一个模拟短字符串的函数。

【问题讨论】:

    标签: c++ enums constants


    【解决方案1】:

    'left' 是一个多字符文字(C++03 的 2.13.2/1),它的类型为 int

    它是由实现定义的它实际具有的整数值。特别是,不能保证 'left''right' 不相等,所以在枚举中使用它们会很失败。

    不过,例如,GCC 在此处记录其行为:http://gcc.gnu.org/onlinedocs/gcc-4.6.1/cpp/Implementation_002ddefined-behavior.html#Implementation_002ddefined-behavior

    'right' 有五个字符,显然不可能每个 5 个字符的字符串都有不同的 32 位值。

    【讨论】:

    • 当然它必须是一致的?为了让字符文字始终获得 0 - 255 范围内的正确值?
    • “一致”是什么意思?每个 C++ 实现都必须定义并记录多字符文字的值(这就是“实现定义”的含义),因此每次运行程序时 'left' 将具有相同的值。不过,不同的编译器可能会给出不同的值。 'c' 不是多字符文字,它的类型为char,等于执行字符集中小写字母“c”的数值。
    • @SSight3:假设没有这样的事情,标准没有要求。在char 签名的系统上,您可能会发现é 的值是负数,而如果您采用平台对它如何形成多字符常量的定义并将其应用于单字符字符串é,你得到一个正值。它们可能等于模 256,这看起来很合理,但这完全取决于实现。
    • @SSight3 扩展史蒂夫的答案,很难看出它是如何做到的:单个字符文字的类型为 char,多字符文字的类型为 int
    • @bobobobo:在 gcc 4.6.1 上,是的,我链接到的文本保证了这一点。在其他版本的 gcc 上,由其等效文档。但是标准中不能保证'left''right' 不相等。如果有人问有关 C++ 的问题,但没有指定任何实现,那么除非另有说明,否则我会从该语言的 POV 回答。
    【解决方案2】:

    多字符常量是您通常想要避免的。假设您的系统是具有 32 位架构的小端序。在这种情况下,'left' 转换为:

    ('l')+('e'<<8)+('f'<<16)+('t'<<24)
    

    请注意,为了便于阅读,我在每个字符后面省略了 int 的转换。

    所以多字符常量实际上是一个整数。

    我曾经使用'BM' 来检查我读取的 .bmp 图像的前两个字节,以检查文件类型是否正确,但很快我决定不值得我保存额外的几个字符。如果你使用大端系统,或者你的int 有不同的大小等等,你会在那里遇到问题。更不用说烦人的编译器警告了。

    如果你有enum,通常有两种情况:

    案例 1,你不关心枚举的值。在这种情况下,你就不要管它们了。第一个将变为零,编译器会逐步填充其余部分。

    案例 2,您需要这些值来达到一个巧妙的目的。在这种情况下,您需要为您的目的一一分配它们。例如,如果您想enum 程序的子系统并且您需要启用、禁用它们,您可以有 1 个变量,它是 enum 的或 (|) 值,如下所示:

    enum subsystem
    {
        SUBSYSTEM_1 = 0x0001,
        SUBSYSTEM_2 = 0x0002,
        SUBSYSTEM_3 = 0x0004,
        SUBSYSTEM_4 = 0x0008,
        SUBSYSTEM_5 = 0x0010,
        /* etc */
    };
    

    (有趣的事实,你知道 C++ 在enum 的最后一个元素之后接受额外的, 吗?)

    在任何情况下,您都不会想要一个对应于'left' 的奇怪值。如果您认为这样可以使代码清晰易读,那么您可以确定常量的名称 (LEFT) 就足够了。

    【讨论】:

    • 更多的是在幕后作为写入值(EG'w+b')的一个聪明的技巧,所以用户可以通过赋值运算符将它传递给一个文件类 - 它可以将它作为int、long 等,并将文件名视为 char 数组。我试图避免这些警告,因为它们看起来难看。
    • 在这种情况下,您可以像我说的第二种情况那样定义值,它们将传递WRITE+BINARY,它更具可读性并且具有相同的语法(请注意,由于enum 的位ed 值不重叠,+ 的作用类似于 |
    猜你喜欢
    • 2010-09-21
    • 1970-01-01
    • 2016-05-16
    • 1970-01-01
    • 2010-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多