在PHP中的64位体系结构上打包/解包64位int

在PHP中的64位体系结构上打包/解包64位int,php,binary,64-bit,pack,unpack,Php,Binary,64 Bit,Pack,Unpack,为什么在x64体系结构上获得以下输出 $ php -r 'echo pow(2, 33) . "\n";print_r(unpack("Ivalue", pack("I", pow(2, 33))));' 8589934592 Array ( [value] => 0 ) 似乎它可以处理签名的64位整数,但它不能打包/解包它们。根据文档,I的大小应该取决于机器,在本例中为64位 $ php -r 'echo PHP_INT_MAX;' 9223372036854775807 $

为什么在x64体系结构上获得以下输出

$ php -r 'echo pow(2, 33) . "\n";print_r(unpack("Ivalue", pack("I", pow(2, 33))));'
8589934592
Array
(
    [value] => 0
)
似乎它可以处理签名的64位整数,但它不能打包/解包它们。根据文档,I的大小应该取决于机器,在本例中为64位

$ php -r 'echo PHP_INT_MAX;'
9223372036854775807

$ php -v
PHP 5.2.9 (cli) (built: Apr 17 2009 03:29:14)
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2009 Zend Technologies

pack(“I”)
请求一个整数,对于x86_64上的I32LP64模型,该整数通常仍然是32位宽-至少在C语言中是这样。解释器通常会在其顶部添加自己的定义。

没有64位版本的PHP 5.2。第一个64位版本是Windows端5.3.0的实验版本。因此,如果您在Windows上使用5.2.9,您必须至少升级到5.3.0才能获得64位版本

如果我的前提是正确的,并且您在Windows上使用PHP,那么这就是它不工作的方式


要访问CPU的64位组件,整个堆栈必须是64位。这意味着CPU必须支持64位,操作系统必须支持64位,应用程序必须支持64位。如果其中任何一个使用32位,则整个堆栈将从该点开始使用32位。它采用最小公分母。

因为pack将第二个参数作为字符串,并将其转换为32位int。就位大小限制而言,唯一的缓解措施是无符号。查看源代码,我看到Perl即将推出一个64位版本,它使用“Q”强制64位机器endian。

下面是一个将任意大小的整数值打包为N位的函数:

function encode_int($in, $pad_to_bits=64, $little_endian=true) {
    $in = decbin($in);
    $in = str_pad($in, $pad_to_bits, '0', STR_PAD_LEFT);
    $out = '';
    for ($i = 0, $len = strlen($in); $i < $len; $i += 8) {
        $out .= chr(bindec(substr($in,$i,8)));
    }
    if($little_endian) $out = strrev($out);
    return $out;
}
函数encode_int($in,$pad_to_bits=64,$little_endian=true){
$in=decbin($in);
$in=str_pad($in,$pad_to_位,'0',str_pad_左);
$out='';
对于($i=0,$len=strlen($in);$i<$len;$i+=8){
$out.=chr(bindec(substr$in$i,8));
}
如果($little_endian)$out=strev($out);
退回$out;
}
下面是一个对压缩整数进行解码的函数:

    function decode_int(&$data, $bits=false) {
            if ($bits === false) $bits = strlen($data) * 8;
            if($bits <= 0 ) return false;
            switch($bits) {
                    case 8:
                            $return = unpack('C',$data);
                            $return = $return[1];
                    break;

                    case 16:
                            $return = unpack('v',$data);
                            $return = $return[1];
                    break;

                    case 24:
                            $return = unpack('ca/ab/cc', $data);
                            $return = $return['a'] + ($return['b'] << 8) + ($return['c'] << 16);
                    break;

                    case 32:
                            $return = unpack('V', $data);
                            $return = $return[1];
                    break;

                    case 48:
                            $return = unpack('va/vb/vc', $data);
                            $return = $return['a'] + ($return['b'] << 16) + ($return['c'] << 32);
                    break;

                    case 64:
                            $return = unpack('Va/Vb', $data);
                            $return = $return['a'] + ($return['b'] << 32);
                    break;

            }
            return $return;
    }
function decode_int(&$data,$bits=false){
如果($bits==false)$bits=strlen($data)*8;

如果($bits
echo PHP_INT_MAX;
给了你什么?你运行的是什么版本的PHP?@Wrikken和@R.Hill,请参见上面的编辑。我也在64位机器上,bin2hex(pack(“I”,pow(2,33))的输出确实是“00000000”,所以不管底层架构如何,机器相关的整数都是32位。我想“依赖于机器”意味着永远不要假设特定的大小,即使是在运行哪个环境。一个想法是:由于pack()不为高于32位整数的任何内容提供显式格式,因此我们不能期望压缩32位以上的整数。在这种情况下,“依赖于机器”实际上意味着16位或32位。