英文:
GoLang bitwise calculation
问题
我有一个缓冲区:
buffer := bytes.NewBuffer([]byte{
0x85, 0x02, 0xFF, 0xFF,
0x00, 0x01, 0x00, 0x02,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x03,
0x41, 0x42, 0x43,
})
我试图返回buffer[8:24]的整数值
我得到了
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1]
不确定如何移动这么大的字节段。
对此还不熟悉。任何帮助都将是很好的。我的初始方法是
requestid := (uint64(buffer.Bytes()[8]&0xff)<<24 + uint64(buffer.Bytes()[9]&0xff)<<16 + uint64(buffer.Bytes()[10]&0xff)<<8 + uint64(buffer.Bytes()[11]&0xff.....)))
但这变得很繁琐,我知道肯定有更简单的方法。
英文:
I have a buffer :
buffer := bytes.NewBuffer([]byte{
0x85, 0x02, 0xFF, 0xFF,
0x00, 0x01, 0x00, 0x02,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x03,
0x41, 0x42, 0x43,
})
I am trying to return the int value of buffer[8:24]
I get
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1]
Not sure how to shift such a large section. of the byte.
new to this. Any help would be great. my initial approach was
requestid := (uint64(buffer.Bytes()[8]&0xff)<<24 + uint64(buffer.Bytes()[9]&0xff)<<16 + uint64(buffer.Bytes()[10]&0xff)<<8 + uint64(buffer.Bytes()[11]&0xff.....)))
but this got tedious, and I know there has to be an easier way.
答案1
得分: 3
你需要进行手动的位移和按位或操作,但是你的代码可以通过删除所有那些buffer.Bytes()
调用来进行清理。
你也不需要&0xff
这部分。n&0xff
的作用是清除0-255
范围之外的所有位。由于缓冲区中的每个值已经是一个字节(0-255),这些操作根本不起作用。如果我们想执行22 & 255
,我们会得到以下结果:
十六进制 | 十进制 | 二进制
--------------|-------------|----------------------
x 0x16 | 22 | 00010110
y 0xff | 255 | 11111111
--------------|-------------|---------------------- AND (&)
0x16 | 22 | 00010110 = x
如你所见,这个操作根本没有任何效果。将x
替换为任何8位值,你将得到相同的结果。x & 0xff
的结果始终是x
。
此外,当你给requestId
赋值时,你从24位开始进行位移。这告诉我你正在读取一个32位整数。那么为什么你继续读取超过32位的值,并将其全部转换为64位整数呢?
如果你正在以大端字节序读取64位整数,请尝试以下代码:
data := buf.Bytes()[8:]
requestid := uint64(data[0])<<56 | uint64(data[1])<<48 |
uint64(data[2])<<40 | uint64(data[3])<<32 |
uint64(data[4])<<24 | uint64(data[5])<<16 |
uint64(data[6])<<8 | uint64(data[7])
如果你正在以小端字节序读取64位整数,请尝试以下代码:
data := buf.Bytes()[8:]
requestid := uint64(data[7])<<56 | uint64(data[6])<<48 |
uint64(data[5])<<40 | uint64(data[4])<<32 |
uint64(data[3])<<24 | uint64(data[2])<<16 |
uint64(data[1])<<8 | uint64(data[0])
如果你正在以大端字节序读取32位整数,请尝试以下代码:
data := buf.Bytes()[8:]
requestid := uint32(data[0])<<24 | uint32(data[1])<<16 |
uint32(data[2])<<8 | uint32(data[3])
如果你正在以小端字节序读取32位整数,请尝试以下代码:
data := buf.Bytes()[8:]
requestid := uint32(data[3])<<24 | uint32(data[2])<<16 |
uint32(data[1])<<8 | uint32(data[0])
二进制包
另外,你可以使用encoding/binary包:
var value uint64
err := binary.Read(buf, binary.LittleEndian, &value)
....
英文:
You have to do the manual bit shifting and OR'ing, but your code can be cleaned up by removing all those buffer.Bytes()
calls.
You also do not need the &0xff
parts. What n&0xff
does, is clear out all bits outside of the 0-255
range. Since each value in the buffer is already a byte (0-255), these operations do nothing at all. If we want to do 22 & 255
, we get the following:
Hexadecimal | Decimal | Binary
--------------|-------------|----------------------
x 0x16 | 22 | 00010110
y 0xff | 255 | 11111111
--------------|-------------|---------------------- AND (&)
0x16 | 22 | 00010110 = x
As you can see, the operation has no effect at all. Replace x
with any 8-bit value and you will see the same result. The outcome of x & 0xff
is always x
.
Additionally, when you assign to the requestId
, you start by shifting by 24 bits. This tells me you are reading a 32-bit integer. Why then do you continue reading values beyond 32 bits and converting it all to a 64 bit integer?
If you are reading a 64-bit int in Big Endian, try this:
data := buf.Bytes()[8:]
requestid := uint64(data[0])<<56 | uint64(data[1])<<48 |
uint64(data[2])<<40 | uint64(data[3])<<32 |
uint64(data[4])<<24 | uint64(data[5])<<16 |
uint64(data[6])<<8 | uint64(data[7])
If you are reading a 64-bit int in Little Endian, try this:
data := buf.Bytes()[8:]
requestid := uint64(data[7])<<56 | uint64(data[6])<<48 |
uint64(data[5])<<40 | uint64(data[4])<<32 |
uint64(data[3])<<24 | uint64(data[2])<<16 |
uint64(data[1])<<8 | uint64(data[0])
If you are reading a 32-bit int in Big Endian, try this:
data := buf.Bytes()[8:]
requestid := uint32(data[0])<<24 | uint32(data[1])<<16 |
uint32(data[2])<<8 | uint32(data[3])
If you are reading a 32-bit int in Little Endian, try this:
data := buf.Bytes()[8:]
requestid := uint32(data[3])<<24 | uint32(data[2])<<16 |
uint32(data[1])<<8 | uint32(data[0])
binary package
Alternatively, you can use the encoding/binary package:
var value uint64
err := binary.Read(buf, binary.LittleEndian, &value)
....
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论