php5 pack在x84_64 env上被打破

时间:2011-04-27 04:34:40

标签: php pack

   pack('H*', dechex(12345678900)) /* on 32bit */  
!= pack('H*', dechex(12345678900)) /* on 64bit */
为什么?

1 个答案:

答案 0 :(得分:1)

我不知道如何修复它,但我想我知道为什么会这样。这里没有错误 - 从手册http://php.net/manual/en/function.dechex.php

中脱颖而出
  

可以转换的最大数字是4294967295(十进制),结果为“ffffffff”

我不知道究竟发生了什么“内部”php,但你可能导致32位无符号整数溢出(12,345,678,900> 4,294,967,295)。由于64位这个限制应该是18,446,744,073,709,551,615,因此dechex返回“正确”值(32对64位差异似乎没有记录,我可能错了,因为我没有64位系统进行测试)。

//编辑:

作为最后的手段,您可以使用GMP extesion为32位系统制作自己的hecdex函数,但这会产生大量的开销。可能会成为现代编程中最慢的实现之一。

// EDIT2:

使用BCMath写了一个函数,我现在在Windows上,并且正在努力为GMP找到正确的dll。

function dechex32($i) {
    //Cast string
    $i = (string)$i;
    //Initialize result string
    $r = NULL;
    //Map hex values 0-9, a-f to array keys
    $hex = array_merge(range(0, 9), range('a', 'f'));
        //While input is lagrer than 0
        while(bccomp($i, '0') > 0) {
            //Modulo 16 and append hex char to result
            $r.= $hex[$mod = bcmod($i, '16')];
            //i = (i - mod) / 16
            $i = bcdiv(bcsub($i, $mod), '16');
        }
    //Reverse result and return
    return strrev($r);
}

var_dump(dechex32(12345678900));
/*string(9) "2dfdc1c34"*/

没有彻底测试但似乎有效。作为最后的手段 - 使用100,000次迭代的粗略基准确实显示,它比原生实现慢约40倍。