gpt4 book ai didi

c# - 使用 Shift 和按位与运算符解析字节数组 C# 中的值

转载 作者:太空宇宙 更新时间:2023-11-03 12:17:47 24 4
gpt4 key购买 nike

我从互联网上抓取了一段代码 ( https://github.com/Cinegy/TsDecoder ),我试图理解它在做什么。

这是构造函数:

public SatelliteDeliverySystemDescriptor(byte[] stream, int start) 
{
Frequency =
$"{(stream[start + 2] >> 4) & 0x0F}{stream[start + 2] & 0x0F}{(stream[start + 3] >> 4) & 0x0F}{stream[start + 3] & 0x0F}{(stream[start + 4] >> 4) & 0x0F}{stream[start + 4] & 0x0F}{(stream[start + 5] >> 4) & 0x0F}{stream[start + 5] & 0x0F}";
OrbitalPosition =
$"{(stream[start + 6] >> 4) & 0x0F}{stream[start + 6] & 0x0F}{(stream[start + 7] >> 4) & 0x0F}{stream[start + 7] & 0x0F}";
WestEastFlag = ((stream[start + 8] >> 7) & 0x01) == 0x01;
Polarization = (byte)((stream[start + 8] >> 5) & 0x03);
RollOff = (byte)((stream[start + 8] >> 3) & 0x03);
ModulationSystem = ((stream[start + 8] >> 2) & 0x01) == 0x01;
Modulation = (byte)(stream[start + 8] & 0x03);
SymbolRate =
$"{(stream[start + 9] >> 4) & 0x0F}{stream[start + 9] & 0x0F}{(stream[start + 10] >> 4) & 0x0F}{stream[start + 10] & 0x0F}{(stream[start + 11] >> 4) & 0x0F}{stream[start + 11] & 0x0F}{(stream[start + 12] >> 4) & 0x0F}";
FECInner = (byte)(stream[start + 12] & 0x0F);
}

我做了什么

var hexString = "430B1200000025E0C610500003";
var hexBytes = Enumerable.Range(0, hex.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
.ToArray();
var descriptor = new SatelliteDeliverySystemDescriptor(hexBytes, 0);

注意:“hexBytes”是:

  [0]: 67
[1]: 11
[2]: 18
[3]: 0
[4]: 0
[5]: 0
[6]: 37
[7]: 224
[8]: 198
[9]: 16
[10]: 80
[11]: 0
[12]: 3

这是输出:

    Frequency = 12000000
OrbitalPosition = 25140
WestEastFlag = true
Polarization = 2
RollOff = 0
ModulationSystem = true
Modulation = 2
SymbolRate = 1050000
FECInner = 3

我的问题

为什么程序员要这样做这是为了得到结果?方法是什么?为什么他要进行所有这些移位和按位与运算符?

        $"{(stream[start + 2] >> 4) & 0x0F}{stream[start + 2] & 0x0F}{(stream[start + 3] >> 4) & 0x0F}{stream[start + 3] & 0x0F}{(stream[start + 4] >> 4) & 0x0F}{stream[start + 4] & 0x0F}{(stream[start + 5] >> 4) & 0x0F}{stream[start + 5] & 0x0F}";

换句话说:这段代码到底发生了什么,难道没有更好的可读性方法吗?

谢谢!

最佳答案

按位运算符通常用于处理字节中的各个位。在 C# 中有 BitArray 类允许您使用位,但我想说它很少使用,可能是因为按位运算符成为此任务的常见做法(还有 BitArray 对于许多可以用按位运算符完成的操作来说是无用的)。

在您的示例中,有一个字节数组对某些数据进行编码,但该数据的各个部分并不由整个字节值表示。相反 - 一个字节可能会在其各个位中编码多条信息。

如果看这个操作:

stream[start + 2] >> 4) & 0x0F

它将第 3 个字节的前半部分(前 4 位)读取为数字。在您的示例中,第 3 个字节是 0x12,二进制形式是 0001 0010。右移,好吧,将给定的位数向右移动:

0001 0010 >> 4 = 0000 0001

现在字节的左半部分移动到右半部分,左半部分变为零。如您所见,现在剩下的一半 0001 和整个字节 0000 0001 代表相同的数字 - 即数字“1”。这就是 >> 4 操作的目标。在那之后执行 & 0x0F 是没有用的,什么也不做,所以我将省略对此的解释。

现在我们得到了左半边,需要得到右半边。我们用

stream[start + 2] & 0x0F

按位与,您可能知道,只保留在两个数字中都设置为(“1”)的位:

0001 0010 &
0000 1111 < this is 0x0F in binary
0000 0010

通过这样做,我们将字节的左半部分归零,现在右半部分归零 (0010),我们得到的数字 (0000 0010) 表示相同的数字 ("2").

所以在结果中我们得到了左半部分(十进制的“1”)和右半部分(十进制的“2”)。您可以看到这用于表示 FrequencyOrbitalPosition 和您案例中的其他几个属性。

让我们看看这个操作:

((stream[start + 8] >> 7) & 0x01) == 0x01

如果我们有字节 abcd efjk 并右移 7 位,我们有:

abcd efjk >> 7
0000 000a

所以我们得到了最左边的位(a)的值。执行 & 0x01 也是无用的,什么也不做,所以可以省略。所以我们可以得出结论,WestEastFlag 标志存储在第 9 个字节的最左边。如果该位为 1 - 设置标志,否则 - 未设置。位移 7 位允许我们到达此标志。

您可以将相同的逻辑应用于其他操作:

(stream[start + 8] >> 5) & 0x03

abcd efkj >> 5
0000 0abc

0000 0abc &
0000 0011 < 0x03
0000 00bc

所以这个允许我们到达位 b 和 c(如果从右边数起,则为 6 和 7),根据该代码,其中存储了 Polarization

为了更好地理解,您可以首先避免不必要的操作(如上所述),也可以使用二进制文字:

// easier to undrestand what's going on, compared to 0x03
(stream[start + 8] >> 5) & 0b0000_0011 // < need last two bits after the shift

为了提高此问题中使用的特定操作集的可读性,您可以创建这样的扩展方法(警告 - 正确测试是否会使用,未正确测试):

public static class ByteExtensions {
public static byte GetBits(this byte x, byte from, byte to) {
if (to > 8)
throw new ArgumentOutOfRangeException(nameof(to));
if (to < from)
throw new ArgumentOutOfRangeException(nameof(from));
x >>= (from - 1);
x &= (byte)(0xFF >> (7 - (to - from)));
return x;
}
}

然后可以使用它执行上述操作。例如:

stream[start + 2] >> 4) & 0x0F // get left half

成为

stream[start + 2].GetBits(5, 8) // get left half (so, bits 5,6,7,8)

(stream[start + 8] >> 5) & 0x03 // get bits 6,7

成为

stream[start + 8].GetBits(6,7)

关于c# - 使用 Shift 和按位与运算符解析字节数组 C# 中的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48985131/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com