为啥有人会在枚举声明中使用 << 运算符?
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,
........
<<
操作数是移位操作数,它将第一个操作数左移第二个操作数中指定的位数。
但是为什么有人会在enum
声明中使用它呢?
【问题讨论】:
@GrantWinney(不是我的近距离投票)但我明白它是如何“基于意见”的,因为问题本质上是“为什么有人在0x04
更易读时使用 1 << 2
我”。
我从来没有说过 0x04 更具可读性,我也没有比较两者。该问题的目的是了解此语句的副作用(= 能够组合标志)
Oscar,您的帖子没有任何问题(我认为这对于学习使用任何 C/C++/C#/Java/javascript 进行编码的人很有用)。但是不同的人阅读相同文本的方式不同——我只是用我的阅读方式来解释投票结束。
我会小心在位移前加一个前导零 - 如果没有 8
或 9
那么文字不会被解释为八进制吗?这可能需要一两个小时的调试时间。
如果你知道 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,
........
【讨论】:
注意:<<
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#,因此整数类型的大小不依赖于平台。 <<
运算符的左操作数的类型决定了使用哪个重载。例如,s
是整数,1 << s
给出 32 位 int
,1u << s
给出 32 位无符号 uint
,1L << s
给出 64 位 long
,1ul << s
是 @ 987654338@, 和(BigInteger)1 << s
或BigInteger.One << 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 << 0
。
因为<<
右边的数字告诉你位数。
.
加长版:
传统上,单词中的位从零开始从右到左编号。 所以最低有效位是第 0 位,当你走向 最重要的位。有几个benefits 来标记位 方式。
一个好处是,无论字长如何,您都可以谈论相同的内容。 例如,我可以说在 32 位字 0x384A 和 8 位字 0x63 中,位 设置了 6 和 1。如果你在另一个方向编号你的位,你不能 这样做。
另一个好处是位的值只是 2 的位次方
位置。例如,二进制 0101
设置了位 2 和 0。位 2 贡献
值4 (2^2)
给数字,位0 贡献值1 (2^0)。所以
number 的值当然是 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)
.
一开始它可能看起来很奇怪和迟钝,但你会习惯的。你会 如果您明确需要知道某事物的位数,将不胜感激。
【讨论】:
【参考方案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的枚举变量,为啥我这就不行了