Perl Perl_4
Perl ビット演算子 ビットストリング (0x221)

目次 - Perl Index
Theme
Perl について、復習を兼ねて断片的な情報を掲載して行く連載その 0x221 回。
Perl のビット演算子に関係する「 ビットストリング 」( bitwise string : ビット文字列 ) を確認する。
ビットストリング
書籍「 初めての Perl 第 6 版 」の P.265 によれば、Perl のビット演算子は、整数以外に「 ビットストリング 」( bitwise string ) を扱えるといいます。
ビット演算子は、オペランド ( operand : 被演算子 ) のいずれかが整数であれば、それを整数として演算しますが、両方のオペランドが文字列だった場合は、これを「 ビットストリング 」として演算すると言います。
「 つまり 」Perl は「 "\xAA" | "\x55" 」の結果を「 \xFF 」と算出します。とありますが、僕はあまり理解出来ていません。
詳しくはドキュメント「 perlop 」に解説があるとのことで、perlop - perldoc.jp を確認することにします。
ビット列演算子
perlop - perldoc.jp の中では、おそらく ビット列演算子 ( Bitwise String Operators ) の部分が「 ビットストリング 」の項目に該当すると思われます。原文では「 Bitwise String 」とあるので、直訳すると「 ビット単位の列 ( 文字列 ) 」になるでしょうか。
ここには次のような解説があります。
二項ビット単位演算子のオペランドが異なった長さの文字列だった場合、 | と ^ の演算子は短い側のオペランドの右側に追加のゼロが ついているとみなします。 一方 & 演算子は長い方のオペランドが短い方に切り詰められます。 この拡張や短縮の粒度はバイト単位です。
オペランドのビットの長さが異なる場合、
・ 「 | 」( OR ) と「 ^ 」( XOR ) は短い方の右側に 0 を追加。
・ 「 & 」( AND ) は長い方の右側が短い方に併せて切りつめられる。
・ この時の拡張や短縮は「 バイト単位 」( 8bit ) で行われる。
ということです。
実際の例示コードを確認します。
例示 XOR
ビット列演算子 では、「 ASCII-based examples 」として次の例示があります。
print "j p \n" ^ " a h";
この「 ^ 」( XOR ) のビット演算は、結果として次の値を出力します。
JAPH
文字列はすべて ASCII コードで演算されています。演算の内訳はバイト単位 ( 8bit ) で次のようになっていると思われます。なお、「 [sp] 」は半角スペースで、「 [0] 」は長さが足りないオペランドの右側を「 ゼロパディング 」していることを意味するものとします。
hex bin
---------------------
j 0x6a 1101010
XOR [sp] 0x20 0100000
---------------------
J 0x4a 1001010 # 大文字 J が得られる
hex bin
---------------------
[sp] 0x20 0100000
XOR a 0x61 1100001
---------------------
A 0x41 1000001 # 大文字の A が得られる
hex bin
---------------------
p 0x70 1110000
XOR [sp] 0x20 0100000
---------------------
P 0x50 1010000 # 大文字の P が得られる
hex bin
---------------------
[sp] 0x20 0100000
XOR h 0x68 1101000
---------------------
H 0x48 1001000 # 大文字の H が得られる
hex bin
--------------------
\n 0x0a 0001010
XOR [0] 0x00 0000000
--------------------
\n 0x0a 0001010 # 改行文字 ( LF ) が得られる
「 XOR 」のビット演算では、"どちらか一方でのみ" ビットが立っている場合に 真 になるので、結果的に「 JAPH\n 」が得られていることがわかります。
例示 OR
次は「 | 」( OR ) の演算です。
print "JA" | " ph\n";
これは結果として次の値を出力します。
jpah
計算の内訳は次の様なものです。
hex bin
--------------------
J 0x4a 1001010
OR [sp] 0x20 0100000
--------------------
j 0x6a 1101010 # 小文字 j が得られる
hex bin
--------------------
A 0x41 1000001
OR [sp] 0x20 0100000
--------------------
a 0x61 1100001 # 小文字 a が得られる
hex bin
--------------------
[0] 0x00 0000000
OR p 0x70 1110000
--------------------
p 0x70 1110000 # 小文字 p が得られる
hex bin
--------------------
[0] 0x00 0000000
OR h 0x68 1101000
--------------------
h 0x68 1101000 # 小文字 h が得られる
hex bin
--------------------
hex bin
-------------------
[0] 0x00 0000000
OR \n 0x0a 0001010
-------------------
\n 0x0a 0001010 # 改行文字 ( LF ) が得られる
「 OR 」のビット演算は、"どちらか一方で" ビットが立っていれば 真 になるので、結果的に「 jpah\n 」が得られていることがわかります。
例示 AND
「 AND 」演算を確認します。「 AND 」のビット演算を行う「 & 」は、ビット長が短いオペランドに併せて長い方のビットの右側が切り詰められます。
print "japh\nJunk" & '_____';
これは結果的に次の出力を得られます。左オペランドの 5 つの「 _ 」に対応する右オペランドは、「 japh\n 」なので、残りの長いビットに当たる「 Junk 」は切り詰められていることが分かります。
JAPH
演算の内訳をみてみましょう。
hex bin
------------------
j 0x6a 1101010
AND - 0x5f 1011111
------------------
J 0x4a 1001010 # 大文字 J が得られる
hex bin
------------------
a 0x61 1100001
AND - 0x5f 1011111
------------------
A 0x41 1000001 # 大文字 A が得られる
hex bin
------------------
p 0x70 1110000
AND - 0x5f 1011111
------------------
P 0x50 1010000 # 大文字 P が得られる
hex bin
------------------
h 0x68 1101000
AND - 0x5f 1011111
------------------
H 0x48 1001000 # 大文字 H が得られる
hex bin
-------------------
\n 0x0a 0001010
AND - 0x5f 1011111
-------------------
\n 0x0a 0001010 # 改行文字 ( LF ) が得られる
「 AND 」のビット演算は、"両方で" ビットが立っている場合に 真 を返すので、結果的に「 JAPH\n 」が得られていることがわかります。
「 ビットストリング 」の AND 演算ルールに従って、長い方のビットで余った右側の部分 ( Junk ) は破棄されています。
XOR の遊び ?
次の「 XOR 」演算からは、なんと「 Perl 」の文字列が得られます。
print 'p N$' ^ " E<H\n";
計算の内訳をみてみましょう。
hex bin
---------------------
p 0x70 1110000
XOR [sp] 0x20 0100000
---------------------
P 0x50 1010000 # 大文字 P が得られる
hex bin
---------------------
[sp] 0x20 0100000
XOR E 0x45 1000101
---------------------
e 0x65 1100101 # 小文字 e が得られる
hex bin
---------------------
N 0x4e 1001110
XOR < 0x3c 0111100
---------------------
r 0x72 1110010 # 小文字 r が得られる
hex bin
---------------------
$ 0x24 0100100
XOR H 0x48 1001000
---------------------
l 0x6c 1101100 # 小文字 l が得られる
hex bin
---------------------
[0] 0x00 0000000
XOR \n 0x0a 0001010
---------------------
\n 0x0a 0001010 # 改行文字 ( LF ) が得られる
面白いですね。
0x221 -> 0x222 へ
次回は、ビット演算で「 数値 」と「 文字列 」のどちらとして演算するのかを明示する方法を確認します。
なお、今回確認したビット演算の使いどころは理解出来ていません。。
参考情報は書籍「 初めての Perl 第 6 版 」を中心に perldoc, Wikipedia および各 Web サイト。それと詳しい先輩。
目次 - Perl Index
Perl mp2 翻訳 Web コンテンツ圧縮の FAQ (d228)
Perl mp2 翻訳 既知のブラウザのバグの回避策をいくつか (d227)
Perl mp2 翻訳 Perl と Apache でのキュートなトリック (d226)
Perl mp2 翻訳 テンプレートシステムの選択 (d225)
Perl mp2 翻訳 大規模 E コマースサイトの構築 (d224)
Perl mp2 翻訳 チュートリアル (d223)
Perl mp2 翻訳 既知のブラウザのバグの回避策をいくつか (d227)
Perl mp2 翻訳 Perl と Apache でのキュートなトリック (d226)
Perl mp2 翻訳 テンプレートシステムの選択 (d225)
Perl mp2 翻訳 大規模 E コマースサイトの構築 (d224)
Perl mp2 翻訳 チュートリアル (d223)