Упаковать / распаковать 64-битный int на 64-битной архитектуре в PHP - PullRequest
4 голосов
/ 16 июля 2010

Почему я получаю следующий вывод для архитектуры x64?

$ 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

Ответы [ 4 ]

2 голосов
/ 31 июля 2012

Вот функция для упаковки целого числа любого размера в 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;
    }
0 голосов
/ 17 июля 2011

64-битной версии PHP 5.2 не существует. Первая 64-битная версия была экспериментальной версией 5.3.0 для Windows. Поэтому, если вы используете 5.2.9 для Windows, вам нужно будет перейти как минимум до 5.3.0, чтобы получить 64-битную сборку.

Если моя предпосылка верна, и вы используете PHP в Windows, значит, это не работает ...

Чтобы иметь доступ к 64-битному компоненту вашего ЦП, весь ваш стек должен быть 64-битным. Это означает, что ЦП должен поддерживать 64-разрядные, ОС должна поддерживать 64-разрядные, а приложение должно поддерживать 64-разрядные. Если какой-либо из них использует 32 бита, весь стек будет 32-битным с этой точки. Идет по наименьшему общему знаменателю.

0 голосов
/ 04 июля 2012

Потому что pack принимает второй параметр в виде строки и преобразует его в 32-разрядный тип int.Единственное облегчение не подписано, поскольку ограничения размера бита.Глядя на исходный код, я вижу 64-битную версию, пришедшую в ближайшее время от Perl, которая использует 'Q' для принудительного вызова 64-битного машинного порядка.

0 голосов
/ 30 декабря 2010

pack("I") запрашивает целое число, которое для модели I32LP64 в x86_64 по-прежнему обычно имеет ширину 32 бита - по крайней мере в C. Переводчики часто добавляют свое собственное определение сверху.

...