我正在理解Perl在我正在阅读的一些代码中解压缩,特别是使用S*
模板。
$data = "FF";
print "$data - ", unpack("S*", $data), "\n";
# > FF - 17990
非常感谢你的帮助
答案 0 :(得分:3)
你在C中的代码看起来(大致)是这样的:
const char *data = "FA";
unsigned short s;
memcpy( &s, data, strlen(data) );
printf("%s = %d\n", data, s);
这只处理你的情况有两个字符,而解包('S *',...)将返回与其输入对应的短裤列表。
为什么呢?打包和解包的主要动机之一是使用C结构更容易地交换二进制数据。
perlpacktut是一个很好的起点。
答案 1 :(得分:3)
unpack 'S'
将两个字节转换为uint16_t
。
#include <stdint.h>
const char *data = "\x46\x41";
uint16_t n;
memcpy(&n, data, sizeof(n)); // n = 0x4146 or 0x4641
在执行此操作之前,请不要忘记检查data
中的字节数!
请注意,它可以根据系统提供两种不同的结果。
在小端系统(例如x86,x64)上,unpack 'S'
也相当于
uint16_t n = (data[1] << 8) | data[0]; // 0x4146
在大端系统上,unpack 'S'
也等同于
uint16_t n = (data[0] << 8) | data[1]; // 0x4641
顺便说一句,您可能会尝试执行以下操作,但由于内存对齐问题,它无法移植:
uint16_t n = *((const uint16_t *)data);
答案 2 :(得分:1)
我正在回答我自己的问题,所以我可能会遇到一些问题,但是我会把它留在这里给将来的任何人。
首先,让我的例子改为
$data = "FA";
print "$data - ", unpack("S*", $data), "\n";
# > FA - 16710
因为“FF”并没有特别的帮助。
问题是:我们是如何从“FA”到16710的?
首先,将字符“F”转换为ASCII值-70。在二进制中,这是0100 0110
(请注意,我填充了一个前导零,因此很明显它是一个完整的字节)。
然后,我们需要'A'-65的ASCII值。二进制,0100 0001
。
因此,我们F
对应0100 0110
,A
对应0100 0001
。
然后我们将这两个二进制值粘合在一起,除了我们首先放置A
:
0100 0001 0100 0110
将0100 0001 0100 0110
转换为十进制会产生16,710
。
注意:我认为字节粘在一起的顺序可能在不同的计算机上有所不同,所以虽然这里的原则应该适用于所有地方,但数字可能是不同。