7

32ビットOSではsignedintip2longが返され、64ビットOSではunsignedintが返されるようです。

私のアプリケーションは10台のサーバーで動作しており、一部は32ビットで一部は64ビットであるため、すべてが同じように機能する必要があります。

PHPのドキュメントには、その結果を常に署​​名なしにするためのトリックがありますが、データベースがすでにデータでいっぱいになっているので、署名してもらいたいと思います。

では、PHPでunsignedintをsignedintに変更するにはどうすればよいでしょうか。

4

5 に答える 5

19

PHP は unsigned integer を型としてサポートしていませんが、sprintfに値を unsigned として解釈させることで、 ip2longの結果をunsigned int文字列に変換するだけで済みます。%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、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はINTUNSIGNEDデータ型を使用し、PHPは符号付き整数を使用するため、MySQLのINET_NTOA()/ INET_ATON()とPHPのip2long()/ long2ip()を混在させることはできないことに注意してください。符号付き整数と符号なし整数を混在させると、データが大幅に混乱します。

于 2010-01-05T20:33:01.133 に答える
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;
} 
于 2012-05-31T22:00:43.140 に答える
1

-誤解された問題、上記のポール・ディクソンの回答を参照してください。


64 ビットの符号なし整数は、PHP5 では技術的にサポートされていません。ネイティブタイプを使用します。上位ビットを失わずに 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) を出力すると「符号なし」整数が表示されます。ただし、これにより、出力を取得して、希望どおりに保存できるはずです。

于 2009-05-16T14:14:47.330 に答える