F450

ブログ > エントリ > Perlでエンディアンをチェック

2006/11/10(金) 20:27:11 (JST)

Perlでエンディアンをチェック

エンディアンとは
例えば16進数で 0x1234ABCD という4バイトのデータを、データの上位バイトからメモリに「12 34 AB CD」と並べる方式をビッグエンディアン (big endian)、データの下位バイトから「CD AB 34 12」と並べる方式をリトルエンディアン (little endian) という。
(「エンディアン - Wikipedia」より引用)
世の中にはビッグエンディアンでもリトルエンディアンでもないエンディアンが存在するらしいですが、今回は無視します。めんどくさいので。(え
さて、たとえば、ビッグエンディアンのマシンで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に代入しています。
もしビッグエンディアンなら$integer0x1234ABCDに等しく、リトルエンディアンなら0xCDAB3412に等しいという、極単純な関数です。
そこで、例えばビッグエンディアンに統一したいならば、リトルエンディアンのマシンではバイトの順番を入れ替える必要があります。
おまけとして、バイトの順番を入れ替える関数も載せておきます:
sub swapBytes {
    my $bytes = shift;

    my @bytes = split('', $bytes);
    my @newBytes = reverse(@bytes);

    return join('', @newBytes);
}
さて、これでエンディアンの違いも乗り越えられるはずです。乗り越える必要が出てくるかどうかは知りませんが。(え

このエントリへのコメント

このエントリにコメントはありません。
※コメントの新規投稿は現在のところ未実装です。