看来,在32位操作系统ip2long
中返回signed int,在64位操作系统中返回unsigned int。
我的应用程序正在处理10台服务器,有些是32位,有些是64位,所以我需要它们以同样的方式工作。
在PHP文档中,有一个技巧可以使结果始终无符号,但由于我的数据库已经充满了数据,我想让它签名。
那么如何在PHP中将unsigned int更改为已签名的?
答案 0 :(得分:15)
PHP不支持无符号整数作为类型,但您可以做的只是将ip2long的结果转换为unsigned int string ,方法是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;
}
}
答案 1 :(得分:3)
Fwiw,如果你使用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'));
查询也更具可读性。
请注意,您可以不将MySQL中的INET_NTOA()/ INET_ATON()与PHP中的ip2long()/ long2ip()混合,因为MySQL使用INT UNSIGNED数据类型,而PHP使用签名整数。混合有符号和无符号整数会严重扰乱您的数据!
答案 2 :(得分:2)
在32位和64位系统上将整数值解释为signed int:
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;
}
答案 3 :(得分:1)
- 明白了问题,请参阅Paul Dixon上面的答案。
PHP5在技术上不支持64位无符号整数。它将使用本机类型。要从64位signed int转换为32位signed int而不丢失高位,您可以屏蔽然后输入转换输出:
$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)将显示“无符号”整数,因为我们已删除高位。但是,这应该允许您获取输出并按照您希望的方式存储它。
答案 4 :(得分: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;
}