为什么有人在枚举声明中使用<<运算符?
我在看我目前在我的项目中的代码,发现这样的事情:
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);
并且它会用所有给定的枚举值做一些事情。