2006/11/10(金) 20:27:11 (JST)
Perlでエンディアンをチェック
エンディアンとは
このファイルをリトルエンディアンのマシンで読み込んで数字として解釈すると、その数字は0xCDAB3412(10進数で3450549266)となってしまいます。
こういった混乱を避けるためにもエンディアンをチェックしておくことは時として重要であると言えます。
(「エンディアン - Wikipedia」より引用)例えば16進数で 0x1234ABCD という4バイトのデータを、データの上位バイトからメモリに「12 34 AB CD」と並べる方式をビッグエンディアン (big endian)、データの下位バイトから「CD AB 34 12」と並べる方式をリトルエンディアン (little endian) という。
世の中にはビッグエンディアンでもリトルエンディアンでもないエンディアンが存在するらしいですが、今回は無視します。めんどくさいので。(え
さて、たとえば、ビッグエンディアンのマシンで0x1234ABCD(10進数で305441741)という数字をファイルに記録すると、ファイルには「\x12\x34\xAB\xCD」と記録されます。このファイルをリトルエンディアンのマシンで読み込んで数字として解釈すると、その数字は0xCDAB3412(10進数で3450549266)となってしまいます。
こういった混乱を避けるためにもエンディアンをチェックしておくことは時として重要であると言えます。
というわけで、以下は簡単にエンディアンを調べる関数。
もしビッグエンディアンなら
そこで、例えばビッグエンディアンに統一したいならば、リトルエンディアンのマシンではバイトの順番を入れ替える必要があります。
おまけとして、バイトの順番を入れ替える関数も載せておきます:
sub checkMachineEndianness { my $integer = unpack('I*', "\x12\x34\xAB\xCD"); if ($integer == 0x1234ABCD) { print "このマシンはビッグエンディアンです。\n"; } elsif ($integer == 0xCDAB3412) { print "このマシンはリトルエンディアンです。\n"; } else { print "このマシンはビッグエンディアンでもリトルエンディアンでもありません。\n"; } }最初の行の
my $integer = unpack('I*', "\x12\x34\xAB\xCD");
で、「\x12\x34\xAB\xCD」というバイト列を符号なしint値に変換して変数$integer
に代入しています。もしビッグエンディアンなら
$integer
は0x1234ABCD
に等しく、リトルエンディアンなら0xCDAB3412
に等しいという、極単純な関数です。そこで、例えばビッグエンディアンに統一したいならば、リトルエンディアンのマシンではバイトの順番を入れ替える必要があります。
おまけとして、バイトの順番を入れ替える関数も載せておきます:
sub swapBytes { my $bytes = shift; my @bytes = split('', $bytes); my @newBytes = reverse(@bytes); return join('', @newBytes); }さて、これでエンディアンの違いも乗り越えられるはずです。乗り越える必要が出てくるかどうかは知りませんが。(え
このエントリへのコメント
このエントリにコメントはありません。