不寻常的无符号短到位交换字节顺序

Unusual unsigned short to bits swapping byte order

我正在读取数据流,准确地说是 64 字节。我想从传入数据的第 480 位开始读取 16 位。不幸的是,我不知道传入的数据类型是什么,它是一堆随机characters/boxes。将其作为无符号短整型 (v) 读入,我得到了我要查找的数字,在本例中为 13。

my $satt_id = unpack("x60v1"), $msgdata); #$satt_id == 13

这导致 $satt_id == 13,即 00000000 00001101。

如果我将数据提取为 16 位(b 或 B),则字符串不会反映 13 的值,而是字节交换或反转。

my $satt_idb = unpack("x60b16", $msgdata); #satt_idb == "10110000 00000000"
my $satt_idB = unpack("x60B16", $msgdata); #satt_idB == "00001101 00000000"

为什么会出现这种情况?我想更改数据并重新发送消息,如果所有消息元素的大小都相同(16 位,只需在解包时打包回去),这将相对容易,但有些是 6、4、2 和1 位。我应该只使用 little-endian b 然后反转吗?更改数据后将其反转回原始顺序,然后将其打包回 b?

完全独立且与 perl 无关,但这在另一个实用程序中困扰着我。我只是通过交换枚举名称中的值来让步。它起作用了,只是当位数超过 4(16 个不同的值)时不太可行。

谢谢!

编辑:我猜这只是与二进制符号有关?貌似是从右边开始的?所以 $satt_idb 是正确的,如果你从右到左阅读的话。因此,为了使它更加用户友好,只需反转、更改,然后再次反转并重新包装?

EDIT2:基本上我正在尝试创建一种用户友好的方法来编辑通过数据流传入的消息。正如我在评论中提到的,如果我想编辑一个从 0 到 1 的位(在消息中代表 true/false),我不希望用户不得不担心编辑八位组的收到的数据,只是 select 来自 true/false 的下拉列表。

如果它与v一起工作,则意味着数据在little-endian byte order,这意味着

0b0000000000001101

存储为

0b00001101 0b00000000

这就是你得到的。


Should I just use little-endian b and then reverse?

没有。如果您将数字转换为文本表示形式(二进制),您可能做错了什么。

如果你确实想要数字的二进制表示,你可以使用

sprintf("%16b", $num)