【发布时间】:2020-06-30 14:52:04
【问题描述】:
我有一个包含0xE1 和0x04 的字节数组,我需要操纵它来生成0x104,我正在努力解决它。我被告知要执行以下操作:
- 0xE1 AND 0x1F = 0x01
- 左移 8 位 = 0x100
- 0x04 添加 0x100 = 0x104
制造商的原始说明:
- 0xE1 大于 0xE0
- 0xE1 AND 0x1F = 0x01
- 左移 8 位 = 0x100
- 读取下一个字节 = 0x04
- 0x04 添加 0x100 = 0x104
我无法让#2 工作。我尝试了this SO question、BitRotator.RotateLeft 方法和BitOperations.RotateLeft 方法的扩展方法,都没有成功获得0x100。我该怎么做才能到达0x100?
我以前从来没有做过位级别的操作,所以我很苦恼。
更新
我正在解析 GPS 报告。报告中有大小为 1 或 2 个字节的字段。如果字节0 的值小于0xE0,则该字段的大小为1 个字节。否则,大小为 2 个字节,我应该使用上述步骤来获得实际值。引用文档:
任何指定为 1 字节/2 字节字段的字段都是使用以下编码的无符号整数: 如果第一个字节小于 0xE0(十进制 224),则字段大小为 1 字节,值为整个字节的值。如果第一个字节大于或等于 0xE0,则字段大小为 2 字节,值是 2 字节字段的 lsb 13 位的值(最高有效字节在前)。
这是我正在使用的方法(LINQPad 中的原型设计):
private static OneTwoField<Type> GetItemType(
ReadOnlySpan<byte> itemBytes) {
if (itemBytes[0] < 224) {
return new OneTwoField<Type>(1, (Type)itemBytes[0]);
}
itemBytes[0..2].DumpToTable();
// What do I do to get to the real value?
var type = ???;
return new OneTwoField<Type>(2, type);
}
DumpToTable() 扩展产生以下结果:
这是OneTwoField<T>:
public struct OneTwoField<T> {
public OneTwoField(
byte size,
T value) {
Offset = size == 1 ? 0 : 1;
Size = size;
Value = value;
}
public int Offset { get; }
public byte Size { get; }
public T Value { get; }
}
这是Type:
[Flags]
public enum Type :
short {
General = 0x00,
Versions = 0x104
}
【问题讨论】:
-
0x100的结果不适合byte那么您使用的实际类型是什么?在一个字节上左循环 8 位应该会产生完全相同的值。请显示您尝试过的确切代码,以便我们帮助查明问题。 -
@juharr,我已经更新了这个问题,提供了更多关于我正在处理的内容以及我如何处理它的信息。
-
那句话说 lsb 13-bits of the 2-byte field。我认为应该是“最后一个”而不是“lsb”?
-
另外,
Type是一个用于枚举的可怕名称,因为它已经是一个类的名称。这显然不是一组标志(这些标志的幂为 2 从 0 开始增加)。看起来你真的只需要常量值,而OneTwoField不需要是通用的 -
这就是文档所说的,所以我无法真正回答这个问题。我所要做的只是文档(在其他领域已被证明是错误的)和制造商提供的关于如何读取其 2 个字节的说明(我现在也引用了它们)。命名现在都悬而未决。我不得不改变它十几次,因为我勉强凑合。应该是
ItemType,但就像我说的,这是一个原型。
标签: c# bit-manipulation bitwise-operators