PHP - unpack as unsigned int

时间:2015-07-29 11:54:08

标签: php

如何将二进制字符串转换为unsigned int?

我在做

$id = unpack('V', substr($dir, $mid * 12, 4))[1];
echo $id . '<br/>';

根据文件,V在哪里

  

无符号长整数(总是32位,小端字节顺序)

它打印-992455690。这怎么可能?

更新:在文档中找到了这个:

  

请注意,PHP在内部将整数值存储为signed。如果解压缩一个大的unsigned long并且它与PHP内部存储的值大小相同,那么即使指定了unsigned unpacking,结果也是负数。

现在的问题是,如果V格式与签名版本完全相同,除了造成混淆之外,它的重点是什么?

2 个答案:

答案 0 :(得分:2)

不幸的是,对于32位PHP发行版,如你的那样,和本地机器字节顺序是英特尔'小端',答案似乎是:没有太多意义有一个单独的V格式而不是l

对于PHP的64位发行版,V格式允许开发人员在解码以允许访问4字节使用值的系统/语言编码的二进制字符串时检索有用信息 - 但是您的问题则转换为“与签名版本相同的64位计算机具有P格式有什么意义。”

除此之外,我建议使用的格式还为任何阅读开发人员提供有关代码意图的有用信息,如(如果使用pack()转换回二进制字符串)二进制表示形式负数将与原始无符号数相同。如果开发人员知道他们将在允许值的极端范围内处理整数,那么他们应该知道为了能够(手动)正确处理溢出/下溢情况。

此外,并且可能值得注意的是,pack的手册仅提供这些代码,每个代码都有一个代码,用于签名值的格式,这些格式始终是机器字节顺序,而无符号值的格式允许指定除了机器订单之外的特定字节顺序。因此,如果您希望在不操作字节顺序的情况下解码在intel(little-endian)上的32位php发行版上本地存储在ARM(big-endian)上的带符号16位值,则必须先解码为无符号16位大端,如果结果数超过此值,则手动减去2 ^ 15。

答案 1 :(得分:2)

我认为解压缩适合您的需要。如果不起作用,请尝试下面的代码。 和小端序一样,我使用ord来计算32位int var的每个字节的ascii,然后计算int值。

$chars = substr($dir, $mid * 12, 4);
return ord($chars[0]) + ord($chars[1]) << 8 + ord($chars[2]) << 16 + ord($chars[3]) << 24.