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

我在看我目前在我的项目中的代码,发现这样的事情:

public enum MyEnum { open = 1 << 00, close = 1 << 01, Maybe = 1 << 02, ........ } 

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

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

这可以让你做这样的事情:

 var myEnumValue = MyEnum.open | MyEnum.close; 

而不需要计数2的倍数的位值。

(喜欢这个):

 public enum MyEnum { open = 1, close = 2, Maybe = 4, ........ } 

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

 [Flags] public enum SomeBitField { open = 1 << 0 //1 closed = 1 << 1 //2 maybe = 1 << 2 //4 other = 1 << 3 //8 ... } 

为了避免手动inputFlags enum的值。

 public enum MyEnum { open = 0x01, close = 0x02, Maybe = 0x04, ........ } 

这是一个枚举,你可以结合。

它的有效含义是这样的:

 public enum MyEnum { open = 1; close = 2; Maybe = 4; //... } 

这只是一个创build[Flags]枚举的更加防弹的方法。

这只是一个更清洁/更直观的书写方式。 1,2,3是比0x1,0x2,0x4等更可读的序列

这里有大量的答案描述这个机制允许你做什么,但不是为什么你想要使用它。 这是为什么。

简洁版本:

这个符号有助于与其他组件进行交互,并与其他工程师进行交stream,因为它明确地告诉你一个字中的哪个位正在被设置或清除,而不是在数字值中隐藏该信息。

所以我可以打电话给你,说:“嘿,打开文件有什么用?” 你会说,“位0”。 而我会写在我的代码open = 1 << 0 。 因为<<右边的数字告诉你位数。

长版本:

传统上,单词中的位从右到左编号,从零开始。 所以最不重要的位是位数0,当你走向最重要的位时,你数了。 以这种方式标记位有几个好处 。

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

另一个好处是,一位的价值只是提高了位的权力。 例如,二进制0101位2和位0被设置。 位2对数字贡献值4 (2^2) ,位0贡献值1(2 ^ 0)。 所以这个数字的值当然是4 + 1 = 5

这个冗长的背景解释给我们带来了一个重要的问题: <<符号只是通过查看来告诉你位数。

语句1 << 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 << 7 。 那样容易。

哦拍。 工程师刚刚发送了勘误表,说应该是位15,而不是7位。没关系,只要将代码更改为ENABLE = 1 << 15

如果ENABLE实际上是同时设置第7位和第1位呢?

ENABLE = (1 << 7) | (1 << 1) ENABLE = (1 << 7) | (1 << 1)

起初可能看起来很怪异,但你会习惯的。 如果你明确地需要知道某些东西的位数,你会感激不尽。

它等于两个幂。

 public enum SomeEnum { Enum1 = 1 << 0, //1 Enum2 = 1 << 1, //2 Enum3 = 1 << 2, //4 Enum4 = 1 << 3 //8 } 

与这样的枚举,你会有这样的function:

 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); 并且它会用所有给定的枚举值做一些事情。