7

看来,在 32 位操作系统中ip2long返回有符号整数,而在 64 位操作系统中返回无符号整数。

我的应用程序在 10 台服务器上运行,有些是 32 位的,有些是 64 位的,所以我需要它们都以相同的方式工作。

在 PHP 文档中,有一个技巧可以使结果始终未签名,但是由于我的数据库已经充满了数据,所以我想对其进行签名。

那么如何在 PHP 中将 unsigned int 更改为已签名的 int 呢?

4

5 回答 5

19

PHP 不支持无符号整数作为一种类型,但您可以简单地将ip2long的结果转换为无符号 int字符串,方法是让sprintf将值解释为 unsigned with %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;
    }
}
于 2009-05-16T14:01:30.123 回答
4

Fwiw, if you're using MySQL it's usually a lot easier and cleaner if you just pass in the IPs as strings to the database, and let MySQL do the conversion using INET_ATON() (when INSERTing/UPDAT(E)'ing) and INET_NTOA() (when SELECTing). MySQL does not have any of the problems described here.

Examples:

SELECT INET_NTOA(ip_column) FROM t;

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

The queries are also much more readable.

Note that you can not mix INET_NTOA()/INET_ATON() in MySQL with ip2long()/long2ip() in PHP, since MySQL uses an INT UNSIGNED datatype, while PHP uses a signed integer. Mixing signed and unsigned integers will seriously mess up your data!

于 2010-01-05T20:33:01.133 回答
2

interpreting an integer value as signed int on 32 and 64 bit systems:

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;
} 
于 2012-05-31T22:00:43.140 回答
1

- 被误解的问题,请参阅上面 Paul Dixon 的回答。


PHP5 在技术上不支持 64 位无符号整数。它将使用本机类型。要从 64 位有符号 int 转换为 32 位有符号 int 而不会丢失高位,您可以屏蔽然后键入 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) 将显示一个“无符号”整数,因为我们已经删除了高位。但是,这应该允许您获取输出并按照您的意愿存储它。

于 2009-05-16T14:14:47.330 回答
0
public function unsigned2signed($num) {     // converts unsigned integer to signed
    $res = pack('i',$num);                  // change to 'l' to handle longs
    $res = unpack('i',$res)[1];
    return $res;
}
于 2021-07-05T21:26:00.270 回答