Int без подписи в подписанный в php - PullRequest
5 голосов
/ 16 мая 2009

Похоже, что в 32-битной ОС ip2long возвращает подписанное int, а в 64-битной ОС возвращается unsigned int.

Мое приложение работает на 10 серверах, некоторые 32-битные, а некоторые 64-битные, поэтому мне нужно, чтобы все они работали одинаково.

В документации PHP есть хитрость, чтобы сделать этот результат всегда без знака, но, поскольку моя база данных уже заполнена данными, я хочу, чтобы она была подписана.

Так как же изменить беззнаковое целое на подписанное в PHP?

Ответы [ 4 ]

15 голосов
/ 16 мая 2009

PHP не поддерживает целые числа без знака как тип, но вы можете просто превратить результат ip2long в беззнаковую int строку , имея sprintf интерпретировать значение как без знака с %u:

 $ip="128.1.2.3";
 $signed=ip2long($ip);             // -2147417597 in this example
 $unsigned=sprintf("%u", $signed); //  2147549699 in this example

Редактируйте, поскольку вы действительно хотели, чтобы оно было подписано даже в 64-битных системах - вот как вы должны преобразовать 64-битное значение + ve в 32-битный эквивалент со знаком:

$ip = ip2long($ip);
if (PHP_INT_SIZE == 8)
{
    if ($ip>0x7FFFFFFF)
    {
        $ip-=0x100000000;
    }
}
3 голосов
/ 05 января 2010

Между прочим, если вы используете MySQL, обычно намного проще и чище, если вы просто передаете IP-адреса в виде строк в базу данных и позволяете MySQL выполнять преобразование с помощью INET_ATON () (когда INSERTing / UPDAT (E) ' ing) и INET_NTOA () (при выборе). MySQL не имеет проблем, описанных здесь.

Примеры:

SELECT INET_NTOA(ip_column) FROM t;

INSERT INTO t (ip_column) VALUES (INET_ATON('10.0.0.1'));

Запросы также гораздо более читабельны.

Обратите внимание, что вы можете не смешивать INET_NTOA () / INET_ATON () в MySQL с ip2long () / long2ip () в PHP, поскольку MySQL использует тип данных INT UNSIGNED, в то время как PHP использует целое число со знаком Смешивание целых чисел со знаком и без знака может серьезно испортить ваши данные!

2 голосов
/ 01 июня 2012

интерпретирует целочисленное значение как int со знаком в 32- и 64-битных системах:

function signedint32($value) {
    $i = (int)$value;
    if (PHP_INT_SIZE > 4)   // e.g. php 64bit
        if($i & 0x80000000) // is negative
            return $i - 0x100000000;
    return $i;
} 
1 голос
/ 16 мая 2009

- Непонятная проблема, см. Ответ Пола Диксона выше.


64-битные целые числа без знака технически не поддерживаются в PHP5. Он будет использовать нативный тип. Чтобы преобразовать 32-разрядное целое число со знаком из 64-разрядного целого числа без потери старшего бита, вы можете замаскировать, а затем набрать cast:

$ip_int = ip2long($ip);
if (PHP_INT_SIZE == 8) // 64bit native
{
  $temp_int = (int)(0x7FFFFFFF & $ip_int);
  $temp_int |= (int)(0x80000000 & ($ip_int >> 32));
  $ip_int = $temp_int;
}

В 64-битной системе при печати этого значения ($ ip_int) будет отображаться целое число без знака, так как мы удалили старший бит. Однако это должно позволить вам взять вывод и сохранить его, как вы хотите.

...