OrangeGardenRoom

技術系のメモ

Perlでビット演算するときの注意

ハマりかけたのでメモ。

結論、perlのビット演算時は、文字列と数値を気をつけないと行けない。

他の演算子は、文字列用と数値用に分かれてるけどこれだけ分かれていない。

 

 

下記のようなコードがある。

my $lan_IP = shift;
my $lan_Mask = shift;

$lan_IP =~ /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
my $a1 = $1; my $a2 = $2; my $a3 = $3; my $a4 = $4;
$lan_Mask =~ /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
my $b1 = $1; my $b2 = $2; my $b3 = $3; my $b4 = $4;

printf "NA:%d.%d.%d.%d\n", $a1 & $b1, $a2 & $b2, $a3 & $b3, $a4 & $b4;

 

実行すると下記のようになる

$ perl ./getnetworkaddress.pl 192.168.1.250 255.255.255.0

NA:10.40.0.0

本来ほしい値は、「NA:192.168.1.0」でないといけない。

 

 

ちなみに、printfの前に下記1行を挿入すると、正しく、192.168.1.0となる。

printf “%d.%d.%d.%d\n”, $a1, $a2, $a3, $a4;

 

基本、Perlはコンパイラが数値か文字列か自動で考えてくれるけど、

今回これが良くなくなってしまった例。

JavaScriptの時に問題になる数値同士の足し算が、文字列として扱われてしまう等の問題は、

演算子が異なる(文字列「.」、数値「+」)ことによって問題無いが、

ビット演算は演算子が一緒なので……。

 

ちょっと小細工が必要です。

2行目で、それぞれ正規表現からとっているところで+0をしてやります。

 

 

my $lan_IP = shift;
my $lan_Mask = shift;

$lan_IP =~ /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
my $a1 = $1+0; my $a2 = $2+0; my $a3 = $3+0; my $a4 = $4+0;
$lan_Mask =~ /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
my $b1 = $1+0; my $b2 = $2+0; my $b3 = $3+0; my $b4 = $4+0;

printf "NA:%d.%d.%d.%d\n", $a1 & $b1, $a2 & $b2, $a3 & $b3, $a4 & $b4;

 

 

こうしてあげることで、正しい値が出るようになります。

 

ちなみに文字列を明示したい場合は、

「.””」(「.”」でもOK)をつけて上げることで可能です。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です