2010-07-16 65 views
4

爲什麼在x64體系結構上獲得以下輸出?在64位架構上在PHP中打包/解壓縮64位int

$ php -r 'echo pow(2, 33) . "\n";print_r(unpack("Ivalue", pack("I", pow(2, 33))));' 
8589934592 
Array 
(
    [value] => 0 
) 

看起來好像它可以處理簽名的64位整數,但它不能打包/解壓縮它們。根據文檔http://us3.php.net/pack,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 
+0

什麼'回波PHP_INT_MAX;'給你? – Wrikken 2010-07-16 13:33:14

+0

您運行的是哪個版本的PHP? – 2010-07-16 13:37:27

+0

@Wrikken和@R。希爾,看看上面的編輯。 – sberry 2010-07-16 13:41:58

回答

0

pack("I")請求的整數,其中,用於在x86_64的I32LP64模型仍然是寬通常爲32位 - 至少在C.口譯經常加上頂部自己定義。

0

沒有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位。它由最低的共同標準決定。

0

由於pack將第二個參數作爲字符串並將其轉換爲32位int。只有位寬限制纔是無符號的。看看源代碼,我看到一個來自Perl的64位版本,它使用'Q'來強制64位機器端。

2

這裏是收拾任何尺寸的整數值爲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; 
} 

這裏是解碼打包整數的函數:

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; 
    }