为啥有人会在枚举声明中使用 << 运算符?

Posted

技术标签:

【中文标题】为啥有人会在枚举声明中使用 << 运算符?【英文标题】:Why would someone use the << operator in an enum declaration?为什么有人会在枚举声明中使用 << 运算符? 【发布时间】:2013-07-27 02:58:47 【问题描述】:

我正在查看我目前在我的项目中的代码,发现如下内容:

public enum MyEnum

    open     = 1 << 00,
    close    = 1 << 01,
    Maybe    = 1 << 02,
    ........

&lt;&lt; 操作数是移位操作数,它将第一个操作数左移第二个操作数中指定的位数。

但是为什么有人会在enum 声明中使用它呢?

【问题讨论】:

@GrantWinney(不是我的近距离投票)但我明白它是如何“基于意见”的,因为问题本质上是“为什么有人在 0x04 更易读时使用 1 &lt;&lt; 2我”。 我从来没有说过 0x04 更具可读性,我也没有比较两者。该问题的目的是了解此语句的副作用(= 能够组合标志) Oscar,您的帖子没有任何问题(我认为这对于学习使用任何 C/C++/C#/Java/javascript 进行编码的人很有用)。但是不同的人阅读相同文本的方式不同——我只是用我的阅读方式来解释投票结束。 我会小心在位移前加一个前导零 - 如果没有 89 那么文字不会被解释为八进制吗?这可能需要一两个小时的调试时间。 如果你知道 C: 阅读 - What is the meaning of this declaration? 【参考方案1】:

这允许你做这样的事情:

var myEnumValue = MyEnum.open | MyEnum.close;

无需计算 2 的倍数的位值。

(像这样):

public enum MyEnum

    open     = 1,
    close    = 2,
    Maybe    = 4,
    ........

【讨论】:

注意&lt;&lt; declaration will give you a maximum of up to 64 different states (on most platforms). If you need more possible states, this solution will not work 什么替代解决方案可以提供超过 64 个正交状态? @GrijeshChauhan 大多数平台?这是 C#,因此整数类型的大小不依赖于平台。 &lt;&lt; 运算符的左操作数的类型决定了使用哪个重载。例如,s 是整数,1 &lt;&lt; s 给出 32 位 int1u &lt;&lt; s 给出 32 位无符号 uint1L &lt;&lt; s 给出 64 位 long1ul &lt;&lt; s 是 @ 987654338@, 和(BigInteger)1 &lt;&lt; sBigInteger.One &lt;&lt; s 给出一个任意大小的整数(需要参考System.Numerics.dll 程序集)。 @JeppeStigNielsen 知道了!...我不是来自c# 背景我觉得我应该分享答案,因为我知道这一点。 ...顺便说一句,如果在 c#、sizeof(enum) > sizeof(one byte) 中,我不喜欢 c#,因为没有人喜欢在他的代码中使用 2^sizeof(int) 符号常量。 @GrijeshChauhan 在 C# 中,您可以像这样创建一个 8 位枚举类型:public enum Color : byte Red, Yellow, Green, Blue, 【参考方案2】:

这通常与位域一起使用,因为它很清楚模式是什么,消除了手动计算正确值的需要,从而减少了出错的机会

[Flags]
public enum SomeBitField

    open = 1 << 0    //1
    closed = 1 << 1  //2
    maybe = 1 << 2   //4
    other = 1 << 3   //8
    ...

【讨论】:

我认为您的意思是按位运算,而不是位域。位域,至少在 C 世界中,是子字节结构成员。【参考方案3】:

为了避免手动输入 Flags 枚举的值。

public enum MyEnum

    open     = 0x01,
    close    = 0x02,
    Maybe    = 0x04,
    ........

【讨论】:

+1。人们可能会在这样的enum 上加上[Flags] 以澄清用法……但并不是每个人都关心。【参考方案4】:

这是为了制作一个可以组合的枚举。

它的实际含义是:

public enum MyEnum

    open = 1;
    close = 2;
    Maybe = 4;
    //...

这只是创建[Flags] 枚举的一种更安全的方法。

【讨论】:

【参考方案5】:

这只是一种更简洁/更直观的方式来编写这些位。 1、2、3 是比 0x1、0x2、0x4 等更易于人类阅读的序列。

【讨论】:

【参考方案6】:

这里有很多答案描述了这个机制允许你做什么,但不是为什么 你会想要使用它。原因如下。

短版:

这种符号有助于与其他组件交互和通信 与其他工程师一起,因为它明确地告诉您单词中的位是什么 设置或清除,而不是在数值中隐藏该信息。

所以我可以打电话给你说“嘿,打开 文件?”你会说,“位 0”。我会在我的代码中写 open = 1 &lt;&lt; 0。 因为&lt;&lt;右边的数字告诉你位数。

.

加长版:

传统上,单词中的位从零开始从右到左编号。 所以最低有效位是第 0 位,当你走向 最重要的位。有几个benefits 来标记位 方式。

一个好处是,无论字长如何,您都可以谈论相同的内容。 例如,我可以说在 32 位字 0x384A 和 8 位字 0x63 中,位 设置了 6 和 1。如果你在另一个方向编号你的位,你不能 这样做。

另一个好处是位的值只是 2 的位次方 位置。例如,二进制 0101 设置了位 2 和 0。位 2 贡献 值4 (2^2) 给数字,位0 贡献值1 (2^0)。所以 number 的值当然是 4 + 1 = 5。

冗长的背景解释让我们明白了这一点:&lt;&lt; 符号只需查看即可告诉您位数。

语句1 &lt;&lt; n 中的数字 1 只是一个设置在 位位置 0。当您将该数字向左移动时,您将移动该集合 位到数字中的不同位置。方便地,您转移的金额 告诉你将要设置的位数。

1 << 5:   This means bit 5.   The value is 0x20.
1 << 12:  This means bit 12.  The value is 0x40000.
1 << 17:  This means bit 17.  The value is 0x1000000.
1 << 54:  This means bit 54.  The value is 0x40000000000000.
          (You can probably see that this notation might be helpful if
          you're defining bits in a 64-bit number)

当您与他人互动时,这种表示法真的会派上用场 组件,例如将字中的位映射到硬件寄存器。就像你可能 有一个设备在您写入位 7 时打开。所以硬件工程师 会写一个数据表,说明第 7 位启用该设备。你会写 你的代码ENABLE = 1 &lt;&lt; 7。就这么简单。

哦,开枪。工程师刚刚向数据表发送了一个勘误表,说它是 应该是第 15 位,而不是第 7 位。没关系,只需将代码更改为 ENABLE = 1 &lt;&lt; 15.

如果ENABLE 实际上是同时设置了第 7 位和第 1 位怎么办?

ENABLE = (1 &lt;&lt; 7) | (1 &lt;&lt; 1).

一开始它可能看起来很奇怪和迟钝,但你会习惯的。你会 如果您明确需要知道某事物的位数,将不胜感激。

【讨论】:

【参考方案7】:

等于二的幂。

public enum SomeEnum

    Enum1 = 1 << 0,    //1
    Enum2 = 1 << 1,    //2
    Enum3 = 1 << 2,    //4
    Enum4 = 1 << 3     //8

有了这样的枚举,你将拥有如下所示的函数:

void foo(unsigned ind flags)

    for (int = 0; i < MAX_NUMS; i++)
        if (1 << i & flags)
        
            //do some stuff...
            //parameter to that stuff probably is i either enum value
        

调用该函数将是foo(Enum2 | Enum3);,它将对所有给定的枚举值执行一些操作。

【讨论】:

以上是关于为啥有人会在枚举声明中使用 << 运算符?的主要内容,如果未能解决你的问题,请参考以下文章

java枚举类型书上也没有在枚举类里声明有static的枚举变量,为啥我这就不行了

为啥有人会在 C# 中使用“in”参数修饰符?

枚举

Java 枚举 - 为啥使用 toString 而不是 name

枚举进行位运算 枚举组合z

有人可以解释为啥条件运算符和赋值运算符一起使用时表现奇怪吗?