c#-获取特定位并获取ushort值的前14位

c#-获取特定位并获取ushort值的前14位,c#,bit-manipulation,bitmask,ushort,C#,Bit Manipulation,Bitmask,Ushort,在阅读了所有关于位移位/掩蔽的问题和答案后,我简直无法将我的头绕在它周围。我只是不理解它在基本层面上是如何工作的。我已经能够通过使用BitArray和BitConverter实现各种技术,但是我真的很想更好地理解位移位/掩蔽 我需要做的具体工作如下: 我有一个ushort:0x810E(33038) 使用位移位/掩蔽,我想知道如何: 获取第16位结果:1 获取第15位结果:0 获取一系列位以创建新的ushort值,特别是 前14位结果:270 正如我所说,我能够使用BitArray执行这些任

在阅读了所有关于位移位/掩蔽的问题和答案后,我简直无法将我的头绕在它周围。我只是不理解它在基本层面上是如何工作的。我已经能够通过使用BitArray和BitConverter实现各种技术,但是我真的很想更好地理解位移位/掩蔽

我需要做的具体工作如下:

我有一个ushort:0x810E(33038)

使用位移位/掩蔽,我想知道如何:

  • 获取第16位结果:1
  • 获取第15位结果:0
  • 获取一系列位以创建新的ushort值,特别是 前14位结果:270
正如我所说,我能够使用BitArray执行这些任务,这是我获得正确结果的方式,但我想了解如何使用位移位/掩蔽执行这些操作


任何帮助都将不胜感激。

屏蔽单个位

您可能知道,
ushort
是一个16位的值,因此给定的数字
0x810E
也可以写成

‭10000001 00001110‬
由于
ushort
没有移位运算符,因此该值首先转换为
int

所以,如果你想得到第15位,你可以得到一个位

000000000 0000000 00000000 00000001
然后向左移动14次(右侧填充
0

您已经创建了一个位掩码

现在,如果将掩码和值与按位的
组合,则只会得到第15位的值:

  ‭00000000 00000000 10000001 00001110‬
& 00000000 00000000 01000000 00000000
= 00000000 00000000 00000000 00000000
又是
0
。要访问此位,您必须将整个结果向右移动14次,并将其转换为
ushort

这可以用以下代码表示:

ushort value_15 = (ushort)(((1 << 14) & value) >> 14);
这将导致
C#
in:

ushort value_15 = (ushort)((value >> 14) & 1);
因此,您避免了一次额外的移位,即使使用 有符号的数字(因为用于符号的最高位通过移位保持不变)

屏蔽位范围

要遮罩一个位范围,您所要做的就是更改遮罩。因此,要获得较低14位的值,可以使用掩码

  00000000 00000000 ‭10000001 00001110‬
& 00000000 00000000 00111111 11111111
= 00000000 ‭00000000 00000001 00001110
C#
中,这可以用

ushort first14bits = (ushort)((0xFFFF >> 2) & value);

其中(
0xFFFF
00000000000000111111111111111111
)。

Endianness在这里只是分散注意力。它与位掩蔽整数值无关,并且可能会让那些无法对位级操作进行研究的人感到困惑。语法和操作完全相同,无论单个整数值的长度是多少,也不管平台端号是多少。而且,在一个班次足够的情况下,做两班倒是一种浪费,一点也不“可以理解”。这只会使代码重复,更难阅读。此外,使用两个移位方法的场景可能会导致天真的程序员实现第二个移位,这可能会填充新的设置位(在这些场景中,另一种选择是强制转换,例如,
1我已经删除了关于endianess的部分。我试图创建一个详尽的答案,但我承认,也许我关注的是不相关的细节。我现在时间不多了,也许我会稍后更改答案。我学到的一件事(因为我不知道)是强制转换。“强制转换是必需的”--是的,在这种情况下,因为预定义的运算符不包括一个用于
ushort
,而隐式强制转换规则将
ushort
强制转换为
int
,而不是
uint
,因此转换的结果是
int
,并且必须强制转换回
ushort
。类似于(ushort)(值>>15和1)`我真的很感谢你的解释。这对我帮助很大……直到彼得说有更好的单班制方法。我会接受这个答案,但是彼得,我希望你能跟进你的单班制答案,这样我们就能看到区别,并确定哪一个更好,更容易理解和阅读。谢谢大家!
  00000000 00000000 ‭10000001 00001110‬
& 00000000 00000000 00111111 11111111
= 00000000 ‭00000000 00000001 00001110
ushort first14bits = (ushort)((0xFFFF >> 2) & value);