背景:
((int)CZSystemType.Api << CZSysConsts.POS_SYSTEM) + ((int)CZModuleType.待办 << CZSysConsts.POS_MODULE) + (0x0001)
公司定义一系列的枚举,出现移位运算符,现在已经忘记差不多,这里总结一下
代码演示:
namespace TestUnit
{
class Program
{
static void Main(string[] args)
{
//Console.WriteLine(((int)CZSystemType.Api << CZSysConsts.POS_SYSTEM) + ((int)CZModuleType.待办 << CZSysConsts.POS_MODULE) + (0x0001));
//Console.WriteLine(0x02);//2
//Console.WriteLine(0x02 << 1);//4
//Console.WriteLine(0x02 << 3);//16
//Console.WriteLine(0x02 << 24);
//33554432即0x02 1021*1024*16
//简单理解就是左移位多少位数,就是乘以2的多少次方,反之除以
//1、给用户创建、读取,修改和删除的权限
permission parmission = permission.Create | permission.Read | permission.Update | permission.Delete;
Console.WriteLine(parmission);
//2、去掉用户的修改和删除权限
parmission = parmission & ~permission.Update;
parmission = parmission & ~permission.Delete;
Console.WriteLine(parmission);
//3、给用户加上修改的权限
parmission = parmission | permission.Update;
Console.WriteLine(parmission);
//4、判断用户是否有创建的权限
var isCreate = (parmission & permission.Create) != 0;
//或者
var isCreate2 = (parmission & permission.Create) == permission.Create;
/*
这时parmission枚举的值将变成0 + 1 + 4 = 5,它的ToSting()将变成“parmission.Create,
parmission.Read”,parmission.Update; 这里我们可以解释为什么第五个值Delete是8而不能成为5。
也就是说它的值不应该是前几项值的复合值。一个比较简单的方法
就是用2的n次方来依次位每一项赋值,例如:1,2,4,8,16,32,64.......。
*/
}
}
///<summary>
/// 权限枚举
/// 注意加了[Flags] 特性后有三种写法,
/// 一种是使用<<符号,
/// 第二种是0x01,
/// 还有一种是直接写0,1,2,4,8....,
/// 一般来说是2的n次方来表示。
/// 注:<<左操作符,表示对这个数进行移位。
///</summary>
[Flags]
public enum permission
{
Unknown = 0, // 也可以写成0x00或0
Create = 1 << 0, // 0x01或1
Read = 1 << 1, //0x02或2
Update = 1 << 2, //0x04或4
Delete = 1 << 3 //0x08或8
}
详细说明如下:
是多种运算符中一种:
https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/operators/
在讲移位运算符之前,先简单补充一下原码与补码的知识。
一.原码与补码
在计算机系统中,数值一律用补码来存储(表示)。主要原因:使用补码,可以将符号位和其他位统一处理;同时减法也可按加法来处理。另外,两个补码表示的数相加时,如果最高位(符号位)有进位,则进位被舍弃。
1.原码转补码分两种情况
(1)正数的补码:与原码相同(已知原码求补码)
例如:+9的原码是0000 1001。补码也是0000 1001。
(2)负数的补码:符号位为1,其余位为该数绝对值的原码按位取反,然后整个数加1。
例如:-7原码为1000 0111(高位为符号位,1表示负数,0表示正数),补码为1111 1001.
2.补码转原码也分两种情况(已知补码求原码)
(1)正数的原码:与补码相同
例如:+9的补码是0000 1001。原码也是0000 1001。
(2)负数的原码:符号位为1,其余位为该该补码按位取反,然后整个数加1。
例如:-7的补码是1111 1001,原码是1000 0111。
二.移位运算符
“<<”和“>>”运算符用于执行移位运算,分别称为左移位运算符和右移位运算符。对于X<<N和X>>N形式的运算,含义是将X向左或向右移动N位,得到的结果的类型与X相同。此处,X的类型只能是int,uint、long或ulong,N的类型只能是int,N的类型只能是int,或者显示转换为这些类型之一,否则变异程序时会出现错误。
1.左移位运算符
使用左移位(<<)运算符可以将数向左移位。其作用是所有的位都向左移动指定的次数,高次位就会丢失,低位以0来填充。
注意:如果第一个操作数是int或uint(32位数),则移位数有第二个操作数的低5位给出(原因是:低5位可表示的数的范围是0~24+23+22+21+20,即0~31,足够一个 32位数移位使用),如果第一个操作数是long或ulong(64位数),则移位数由第二个操作数的低6位给出(原因同上)。在左移时,第一个操作数的高序位被放弃,低序空位 用0填充。移位操作从不导致溢出。
(1)正数左移位(以85为例,可以视作int 、long、uint、ulong之一,此处视为uint类型,32位)
85的二进制表示: 0000 0000 0000 0000 0000 0000 0101 0101
85左移(<<)3位: 0000 0000 0000 0000 0000 0010 1010 1000
移位后的结果十进制表示: 680
(2)负数左移位(以-85为例,可以视作int 、long之一,此处视为int,32位)
-85的二进制补码表示: 1111 1111 1111 1111 1111 1111 1010 1011
-85左移(<<)3位: 1111 1111 1111 1111 1111 1101 0101 1000
移位后结果的原码表示: 1000 0000 0000 0000 0000 0010 1010 1000
移位后的结果十进制表示: -680
2.右移位运算符
右移位运算符(>>)是把数向右移位,其作用是所有的位都向右移动指定的次数。
注意:如果第一个操作数是int或uint(32位数),则移位数有第二个操作数的低5位给出(原因是:低5位可表示的数的范围是0~24+23+22+21+20,即0~31,足够一个 32位数移位使用),如果第一个操作数是long或ulong(64位数),则移位数由第二个操作数的低6位给出(原因同上)。如果第一个操作数为int或long,则右移位是算数移 位(高序空位设置为符号位)。如果第一个操作数是uint或ulong类型,则右移位是逻辑移位(高位填充0)。
(1)正数右移位(以85为例,可以视作int 、long、uint、ulong之一,按哪个规则都行)
85的二进制表示: 0000 0000 0000 0000 0000 0000 0101 0101
85右移(>>)3位: 0000 0000 0000 0000 0000 0000 0000 1010
移位后的结果十进制表示: 10
(2)负数右移位(以-85为例,可以视作int 、long之一,此处视为int,32位)
-85的二进制补码表示: 1111 1111 1111 1111 1111 1111 1010 1011
-85左移(>>)3位: 1111 1111 1111 1111 1111 1111 1111 0101
移位后结果的原码表示: 1000 0000 0000 0000 0000 0010 0000 1011
移位后的结果十进制表示: -11
后一部分:看见https://www.cnblogs.com/tjudzj/p/4190878.html这篇博文写的很详细