我正在使用Visual Studio 2015在vb.net中编写程序。我试图弄清楚如何修改16位整数中的各个位。数字数据类型的字节顺序是小印度语,如下所示:
Field: [ origin ] [tagged] [addressable] [protocol] Bits: 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
在下面的示例代码中,我试图弄清楚如何在变量" i"中设置原点,标记,可寻址和协议。这是一个16位整数。
Dim i As UInt16 = 0
Dim origin As Byte = 0 ' Message origin indicator
Dim tagged As Byte = 0 ' Determines usage of the Frame Address target field (0 or 1)
Dim addressable As Byte = 0 ' Message includes a target address (0 or 1)
Dim protocol As UInt16 = 1024 ' Protocol number: must be 1024 (decimal)
任何人都可以提供一个vb.net示例,说明如何更新变量" i"这样它包含原点,标记,可寻址和协议的位值?
答案 0 :(得分:0)
您可以使用or
组合设置各个位,>>
和<<
组合移位。
例如,要设置标记,可寻址和协议的两个字节,您可以执行以下操作:
Dim tagged As Byte = 1 ' Determines usage of the Frame Address target field (0 or 1)
Dim addressable As Byte = 1 ' Message includes a target address (0 or 1)
Dim protocol As UInt16 = 1026 ' Protocol number: must be 1024 (decimal)
sendbuf(0) = sendbuf(0) or tagged ' bit 0
sendbuf(0) = sendbuf(0) or (addressable << 1) ' bit 1
sendbuf(0) = sendbuf(0) or ((protocol << 2) and 255) ' first 6 bits of protocol
sendbuf(1) = sendbuf(1) or (protocol >> 6) ' next 6 bits of protocol
您可能需要对其进行调整 - 我没有按照链接进行操作,因此我不能完全确定哪些位应该放在哪里(有14位适合2个字节)。 / p>
答案 1 :(得分:0)
使用枚举中的二进制值映射位值。 1 = 1,2 = 10,4 = 100等。然后您可以使用枚举分配变量。您还可以将值组合到新的枚举中(请参阅ProtocolX)。
要提供初始值,只需添加要使用的枚举。
' switch bits on 1, 5, 13, 14, 16
i = FrameSectionEnum.ProtocolBit1 + FrameSectionEnum.ProtocolBit5 +
FrameSectionEnum.AddressableBit13 +
FrameSectionEnum.TaggedBit14 + FrameSectionEnum.OriginBit16
PrintBits(i)
要打开某些位并保留其他位,请使用OR。
' switch bits on 2 and 3 using a combined value. preserve other bits
i = SetOn(i, FrameSectionEnum.ProtocolX)
PrintBits(i)
要关闭某些位并保留其他位,请使用AND和NOT。
' switch bits off 1 and 5
i = SetOff(i, FrameSectionEnum.ProtocolBit1 + FrameSectionEnum.ProtocolBit5)
PrintBits(i)
检查某些位是否打开:
Function CheckBit(i As Integer, bit As FrameSectionEnum) As Integer
Return If((i And bit) = bit, 1, 0)
End Function
设置位,保留其他位:
Function SetOn(i As Integer, bit As FrameSectionEnum) As Integer
Return i Or bit
End Function
关闭位,保留其他位:
Function SetOff(i As Integer, bit As FrameSectionEnum) As Integer
Return i And (Not bit)
End Function
Module Module1
Enum FrameSectionEnum
ProtocolBit1 = 1
ProtocolBit2 = 2
ProtocolBit3 = 4
ProtocolBit4 = 8
ProtocolBit5 = 16
ProtocolBit6 = 32
ProtocolBit7 = 64
ProtocolBit8 = 128
ProtocolBit9 = 256
ProtocolBit10 = 512
ProtocolBit11 = 1024
ProtocolBit12 = 2048
AddressableBit13 = 4096
TaggedBit14 = 8192
OriginBit15 = 16384
OriginBit16 = 32768
ProtocolX = ProtocolBit2 + ProtocolBit3
End Enum
Sub Main()
Dim i As UInt16 = 0
' switch bits on 1, 5, 13, 14, 16
i = FrameSectionEnum.ProtocolBit1 + FrameSectionEnum.ProtocolBit5 +
FrameSectionEnum.AddressableBit13 +
FrameSectionEnum.TaggedBit14 + FrameSectionEnum.OriginBit16
PrintBits(i)
' switch bits on 2 and 3 using a combined value. preserve other bits
i = SetOn(i, FrameSectionEnum.ProtocolX)
PrintBits(i)
' switch bits off 1 and 5
i = SetOff(i, FrameSectionEnum.ProtocolBit1 + FrameSectionEnum.ProtocolBit5)
PrintBits(i)
Console.ReadKey(True)
End Sub
Function SetOn(i As Integer, bit As FrameSectionEnum) As Integer
Return i Or bit
End Function
Function SetOff(i As Integer, bit As FrameSectionEnum) As Integer
Return i And (Not bit)
End Function
Function CheckBit(i As Integer, bit As FrameSectionEnum) As Integer
Return If((i And bit) = bit, 1, 0)
End Function
Sub PrintBits(i As Integer)
Console.Write(CheckBit(i, FrameSectionEnum.OriginBit16))
Console.Write(CheckBit(i, FrameSectionEnum.OriginBit15))
Console.Write(CheckBit(i, FrameSectionEnum.TaggedBit14))
Console.Write(CheckBit(i, FrameSectionEnum.AddressableBit13))
Console.Write(CheckBit(i, FrameSectionEnum.ProtocolBit12))
Console.Write(CheckBit(i, FrameSectionEnum.ProtocolBit11))
Console.Write(CheckBit(i, FrameSectionEnum.ProtocolBit10))
Console.Write(CheckBit(i, FrameSectionEnum.ProtocolBit9))
Console.Write(CheckBit(i, FrameSectionEnum.ProtocolBit8))
Console.Write(CheckBit(i, FrameSectionEnum.ProtocolBit7))
Console.Write(CheckBit(i, FrameSectionEnum.ProtocolBit6))
Console.Write(CheckBit(i, FrameSectionEnum.ProtocolBit5))
Console.Write(CheckBit(i, FrameSectionEnum.ProtocolBit4))
Console.Write(CheckBit(i, FrameSectionEnum.ProtocolBit3))
Console.Write(CheckBit(i, FrameSectionEnum.ProtocolBit2))
Console.Write(CheckBit(i, FrameSectionEnum.ProtocolBit1))
Console.WriteLine()
End Sub
End Module
答案 2 :(得分:0)
问题中的标题格式包含将所有位都放在正确位置的关键。就我个人而言,如果使用从零开始的索引对位进行重新编号,则更容易可视化:
Field: [ origin ] [tagged] [addressable] [protocol] Bits: 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
从origin
字段开始,它需要向左移动14位,这可以这样做:
origin << 14
tagged
和addressable
字段需要分别向左移位13位和12位,这可以通过相同的方式完成。 protocol
字段已经在正确的位置,因此不需要移位。它们都可以与Or
运算符组合在一起,如下所示:
i = (origin << 14) Or (tagged << 13) Or (addressable << 12) Or protocol
需要解决的最后一个细节是,在VB.NET中,位移操作取决于要移位的数据类型。在上面的代码中,origin
,tagged
和addressable
变量都是Byte
类型。这种类型的移位都将以模8(一个字节中的位数)完成,这意味着9位的移位与1位的移位相同。
因为我们所有的移位都超过了8位,所以我们需要转换为更宽的数据类型,否则事情就不会在正确的位置结束。执行此操作的简单方法是将所有变量的声明更改为UInt16
:
Dim i As UInt16
Dim origin As UInt16 = 0
Dim tagged As UInt16 = 0
Dim addressable As UInt16 = 0
Dim protocol As UInt16 = 1024
i = (origin << 14) Or (tagged << 13) Or (addressable << 12) Or protocol
替代方法是保持变量按原样声明,并在进行轮班之前使用CType
转换字段:
Dim i As UInt16 = 0
Dim origin As Byte = 0
Dim tagged As Byte = 0
Dim addressable As Byte = 0
Dim protocol As UInt16 = 1024
i = (CType(origin, UInt16) << 14) Or (CType(tagged, UInt16) << 13) Or (CType(addressable, UInt16) << 12) Or protocol
就个人而言,由于简洁,我更喜欢第一种方式,但选择权在你手中!