按位运算(Bitwise),包括与(&)、或(|)、非(~)、异或(^)共4种运算。 移位(shift)运算,包括左移(<<)、右移(>>)、无符号右移(>>>)共3种。
整数的位运算操作简单,但细节不少,使用时需要留心检查,以便确认结果是否正确。
细节1:位运算适用于整数类类型和字符类型包括 sbyte(System.SByte)、byte(System.Byte)、short(System.Int16)、ushort(System.UInt16)、 int(System.Int32)、 uint(System.UInt32)、 long(System.Int64)、 ulong(System.UInt64)、 nint(System.IntPtr)、 nuint(System.UIntPtr)、 char(System.Char)。
细节2: 这些操作针对 int、 uint、 long、 ulong 类型定义也就是说,这些操作本质上是在32位或64位整数上进行的,其结果也是这些类型。 (包括nint和nuint,nint和nuint由平台定义,要么是32位,要么是64位的整数)。 如果两个操作数都是其他整数类型(sbyte、byte、short、ushort 或 char), 它们的值将转换为 int 类型,结果类型也是 int 类型。 如果操作数是不同的整数类型,它们的值将转换为最接近的包含整数类型。
示例代码说明为了方便展示,下面代码引入了一个自定义方法 string BitStr(整数类类型),用来显示整数的二进制形式,例如:
BitStr((byte)2) 返回 "0b_0000_0010"
BitStr(16) 返回 "0b_0000_0000_0000_0000_0000_0000_0001_0000"
BitStr(-1) 返回 "0b_1111_1111_1111_1111_1111_1111_1111_1111"
当然,也可以直接使用 Convert.ToString(value, 2) 来得到二进制字符串,只是格式略有不同。
在C# 交互窗口(C# Interactive) 环境中,很容易输入和运行一些代码片段,用来进行一些功能验证。 具体操作方式是,在vs2022中,选择菜单: 视图(View)--- 其它窗口(Other Windows)--- C# 交互窗口(C# Interactive)。
~ 逻辑非(NOT)运算,一元操作,只有一个运算数按位非(求反)运算,在每一位上,1变为0,0变为1。
按位与运算,在两个操作数每一对应位上,都是1才为1,否则为0。
按位与运算,在两个操作数每一对应位上,只要有1则为1,全部0才为0。
按位与运算,在两个操作数每一对应位上,相同则为0,不同则为1。
所有数位向左移动,高位丢弃,低位补0。
移位运算符的移位计数说明:因为按位运算的操作是针对32位或64位整数定义的,所以能够移动的位数是有范围的, 对于 x << count 来说,
如果 x 的类型为 int 或 uint,则移位计数由右侧操作数的低阶五位定义。 即 count = count & 0b_1_1111,也等于 count = count % 32, 实际移动位数在0和31之间。
如果 x 的类型为 long 或 ulong,则移位计数由右侧操作数的低阶六位定义。 即 count = count & 0b_11_1111,也等于 count = count % 64, 实际移动位数在0和63之间。
右移位运算和左移位运算一样,移位计数有相同的限制。
右移位运算分为两种,一种是算术右移位运算,一种是逻辑右移位运算, 它们的区别在于移位的是有符号数类型,还是无符号数类型,它们最高位的处理不一样。
算术右移位运算对于有符号数类型,执行算术右移位。 移位时,最低位舍弃,最高位补符号位。 也就是说,原来最高位是0的,右移时继续补0。 原来最高位是1的,右移时继续补1。
最高位为0时是正数,最高位为1时是负数。 所以在右移位过程中,符号保持不变。
对于无符号数类型,进行逻辑右移位。 移位时,最低位舍弃,最高位补0。
为了方便,C# 11 开始引入无符号右移,不区分有符号数和无符号数, 移位时,最低位舍弃,最高位补0。
例如,对于 a >>= 3,a 的类型保持不变。显然,这是必须的。觉得可以这样理解, 在运算过程中,遵循的规则和上面所说的一样,但系统根据需要,对结果进行处理, 把结果转化为a的类型(比如舍弃了不需要的高位字节)。
第一,&(逻辑 AND)、|(逻辑 OR)和 ^(逻辑异或)同样用于bool类型,它们有类似的逻辑,但是细节上有很多不同,应视为不同的类别。
bool 类型的逻辑运算,操作数包括 true、false、null 这3个不同的值,运算结果也是 true、false、null 这3个值之一。
第二,条件逻辑运算符,&&(条件逻辑与)和 ||(条件逻辑或)在执行过程中,有值得注意的地方。
条件逻辑运算有短路特性,当参与运算的表达式有多个时,如果根据计算顺序能提前知道结果,则后面的表达式将被忽略,它们不会被计算。
例如语句 if(f1(a, b) || f2(a, b, c)) { // 代码...},如果 f1(a, b) == true,显然 if 的条件肯定是成立的,此时 f2(a, b, c) 是不会被执行的。
需要非常清楚这一点,因为 f2 的执行与否,根据实际具体代码的不同,可能会产生不同的影响。
移位运算的一个实际应用例子本文示例里面用到的 BitStr 方法,就是通过移位来实现把整数变为二进制字符串的功能。下面是其中的一个主要函数:
此外,和位运算相关的,还有一些重要的内容,如:
(1)运算符优先级。
(2)所有枚举类型支持 ~、&、| 和 ^ 运算符。
(3)用户定义的类型可以重载~、<<、>>、>>>、&、| 和 ^ 运算符。
(4)其它内容。
限于篇幅,这里省略,请查看相关文档。
转载请注明来自夕逆IT,本文标题:《左移运算符优先级(C语言学习笔记10按位运算和移位运算)》
还没有评论,来说两句吧...