1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

PHPのビット演算で詰まったから書置き

Last updated at Posted at 2018-06-08

あらまし

 PHPの中で、IPアドレスとサブネットマスクをチェックする機能を作ろうとしが、その際にビット演算が上手く出来なかった。ビット演算を初めてやる自分が理解してないだけかもしれないけど、同じような人がいたときのためにここに置いておく。

(チェッカのソースは)ないです

やりたかったこと

 IPアドレスをip2long()で数値に変換 → 変換された数値をさらにdecbin()を使って2進数に変換 → ビット演算

作業環境

 ・Win10のIISとPHP7.2
 ・一応Ubuntuでも同じことを確認したけど、バージョンとか忘れた

実際にやったこと

php中に以下のようなコードを書いた。

<?php
//IPを数値とビットに変換
  $IP = "192.168.1.1";
  $lIP = ip2long($IP);
  $bIP = decbin($lIP);
  echo "IP:" . $IP . "\n";
  echo "lIP:" . $lIP . "\n";
  echo "bIP:" . $bIP . "\n";

//Maskを数値とビットに変換
  $Mask = "255.255.255.0";
  $lMask = ip2long($Mask);
  $bMask = decbin($lMask);
  echo "M:" . $Mask . "\n";
  echo "lM:" . $lMask . "\n";
  echo "bM:" . $bMask . "\n";

//なんか色々計算
  $nBMask = ~$bMask;
  echo "nBM:" . $nBMask . "\n";

  $and = $bIP & $bMask;
  $or = $bIP | $bMask;
  $xor = $bIP ^ $bMask;
  echo "&:" . $and . "\n";
  echo "|:" . $or . "\n";
  echo "^:" . $xor . "\n";
?>

実行結果1

IP:192.168.1.1
lIP:3232235777
bIP:11000000101010000000000100000001
M:255.255.255.0
lM:4294967040
bM:11111111111111111111111100000000
nBM:��������������������������������
&:11000000101010000000000100000000
|:11111111111111111111111100000001
^:�������������

ご覧の通り、notとxorの結果が化け化けである。
それでは修正しましょう。

修正

あらかじめ修正しておいたものをこちらに用意しました。

<?php
  $IP = "192.168.1.1";
  $lIP = ip2long($IP);
  $bIP = decbin($lIP);
  echo "IP:" . $IP . "\n";
  echo "lIP:" . $lIP . "\n";
  echo "bIP:" . $bIP . "\n";

  $Mask = "255.255.0.0";
  $lMask = ip2long($Mask);
  $bMask = decbin($lMask);
  echo "M:" . $Mask . "\n";
  echo "lM:" . $lMask . "\n";
  echo "bM:" . $bMask . "\n";

  $nLMask = ~$lMask;
  $nBMask = decbin($nLMask); //数値をビット反転させてから、2進数に変換
  echo "nLM:" . $nLMask . "\n";
  echo "nBM:" . $nBMask . "\n";

  $and = $bIP & $bMask;
  $or = $bIP | $bMask;
  $xor = decbin($bIP ^ $bMask); //数値の排他的論理和を計算してから、2進数に変換
  echo "&:" . $and . "\n";
  echo "|:" . $or . "\n";
  echo "^:" . $xor . "\n";
?>

実行結果2

IP:192.168.1.1
lIP:3232235777
bIP:11000000101010000000000100000001
M:255.255.0.0
lM:4294901760
bM:11111111111111110000000000000000
nLM:-4294901761
nBM:1111111111111111111111111111111100000000000000001111111111111111
&:11000000101010000000000000000000
|:11111111111111110000000100000001
^:0

#まとめ
なんか実際のコードは$nBMaskの値もうちょっと短かったけど、とりあえず修正できた。
phpのビット演算は、2進数では計算できない。10進数で計算してから、2進数に変換させよう。
この後、nBMaskからわざわざIPに戻す操作もしたような気がするけど忘れた。思い出したら書くかも。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?