【问题标题】:hexadecimal in typedef enum in CC中typedef枚举中的十六进制
【发布时间】:2016-10-05 16:16:07
【问题描述】:

我正在寻找在 C 中 typedef enum 中使用十六进制的原因。

我点击了以下链接,但有两个答案: c, obj c enum without tag or identifier

LearnCocos2D 说,“使用十六进制数字没有任何好处,特别是从 a 到 f(10 到 15)开始十六进制数字是没有意义的。”

Sulthan 说,“当整数是二进制掩码时,通常使用十六进制数”。我搜索了二进制掩码,并通过以下链接了解它是位图游戏中使用的一种技术https://en.wikipedia.org/wiki/Mask_(computing)

如果 sulthan 是对的,请帮助我理解它。

我没有足够的声誉来发表评论,所以我创建了这个作为新问题。

【问题讨论】:

  • 要了解为什么要在枚举中使用十六进制,您需要了解为什么要使用十六进制。 typedef 枚举真的没有什么特别之处。
  • 可以使用十六进制,因为在正确的上下文中,它对程序员来说比十进制更具可读性,尽管对于初学者来说,在他们熟悉十六进制之前它可能看起来不太可读.您提到了位掩码,它在头脑中更容易从十六进制转换为二进制,而不是十进制,并且不知何故,它使它们的预期用途更加明显:作为掩码而不是值。例如,掩码可能会隔离处理器寄存器中的特定位,而不是用作计算的值。
  • 当使用int 范围之外的十六进制值时,会出现使用十六进制表示法的缺点。使用 4 字节 int/unsigned0x80000000 是 UB,因为它违反了“枚举常量应为整数常量表达式,其值可表示为 int”。即使它看起来不错。然而,大多数编译器以通常希望的方式处理这个问题。
  • @chux:这不仅仅是未定义的行为,而是违反约束;任何符合标准的编译器都必须至少发出警告。 (默认情况下,gcc 显然不会对此发出警告。默认情况下,gcc 不是符合标准的 C 编译器。)
  • @KeithThompson 也许我的观点表述得不好。 MSVC 不使用#define INT_MIN (-2147483648),因为取反的值是从一个正值开始的,不能用 32 位的int 表示,这是我认为 chux 写的。

标签: c enums


【解决方案1】:

对于位掩码,它有助于查看二进制值,因为这是位掩码所需的级别。而且每个枚举值通常只设置一个位。

因此枚举值将设置(以二进制形式)为0000100010001000100010000 等。

相同的十进制值是:124816 等。

在十六进制中,它们将是 0x010x020x040x080x10 等。

这实际上只是一个偏好问题,但由于十六进制是 2 的幂,它与二进制的关系比十进制更好。这使得这些值表示位掩码值更加清晰。

【讨论】:

    【解决方案2】:

    链接问题中的示例(本问题中未引用)是:

    enum {
        easySprite      = 0x0000000a,
        mediumSprite    = 0x0000000b,
        hardSprite      = 0x0000000c,
        backButton      = 0x0000000d,
        magneticSprite  = 0x0000000e,
        magneticSprite2 = 0x0000000f
    };
    

    这会创建一个匿名枚举类型;您不能定义该类型的对象。所以实际上,声明所做的唯一事情就是定义一组int 常量(枚举常量的类型总是int),并以十六进制指定它们的值。

    这可以说是对enum 构造的滥用,该构造主要用于创建类型,但它是不使用宏定义整数常量的唯一真正方法。 (const int easySprite = 0x0000000a; 不会使 easySprite 成为常​​量表达式。)

    第一个值为0xa(十进制10),其他值按顺序排列。

    这个:

    enum {
        easySprite      = 10,
        mediumSprite    = 11,
        hardSprite      = 12,
        backButton      = 13,
        magneticSprite  = 14,
        magneticSprite2 = 15
    };
    

    意思完全一样。就此而言,这也是如此,尽管它不太明确:

    enum {
        easySprite = 10,
        mediumSprite,   
        hardSprite,     
        backButton,     
        magneticSprite, 
        magneticSprite2
    };
    

    那么为什么要使用十六进制呢?我的猜测是easySpritemediumSprite 等的值是在某个接口中定义的(链接的问题提到了 OpenGL),无论出于何种原因,以十六进制定义值都很方便。也许这些值与其他一些值按位与,形成一个位模式,其低 4 位指定精灵的种类,其他位指定其他信息。写0x0000000a 而不是等价的0xa 可能是为了清楚地表明它是一个完整的32 位值的(一部分)。不看上下文是不可能确定的。

    无论如何,在这里使用十六进制肯定没有错,并且考虑到上下文,它可能比等效的十进制更清晰。

    (谷歌搜索“OpenGL MagneticSprite”只有三个左右的命中,所以我怀疑这是 OpenGL 规范的一部分。谷歌搜索 mediumSprite 会发现很多关于软饮料的信息。)

    【讨论】:

      【解决方案3】:

      为了完成 rmaddy 的回答,另一种写作方式可以使位掩码值在没有十六进制数字的情况下更明显:

      typedef enum
      {
          // empty bitmask
      
          empty_mask = 0,
      
          // bitmask values
      
          first_bit   = 1 << 0,
          second_bit  = 1 << 1,
          third_bit   = 1 << 2,
      
          // bitwise combinations
      
          both_first_and_second = first_bit | second_bit
      } My_enum;
      

      移位运算符&lt;&lt; 消除了解释十六进制值的需要。 组合可以在“核心”值之后声明。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-06-01
        • 1970-01-01
        • 2011-12-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-03
        相关资源
        最近更新 更多