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);
}
さて、これでエンディアンの違いも乗り越えられるはずです。乗り越える必要が出てくるかどうかは知りませんが。(え

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

このエントリにコメントはありません。

コメント新規投稿

サインインすると投稿できる文字数が増えます。
名前:
URL:
コメント:
注意事項
  • コメントの内容は、公序良俗に反しないようにして下さい。
  • 投稿されたコメントは、サイト管理人によって恣意的に修正や削除が行われることがあります。
  • サインインしてコメントを投稿すれば、後から投稿者自身で編集することもできます。ただし、回数制限等があります。
  • コメントではMarkdownを使用することができます(HTMLタグについては一部のみ可)。
  • コメントできる文字数は、サインインしているかどうかなどユーザの状態によって違います。
  • コメントを投稿すると、それに付随する情報(コメントを投稿した時間, サインイン中のアカウントに関する情報, アクセス元IPアドレス, etc.)がサーバに保存され、一部または全部が公開されることがあります(ただし、一般にはこれらの情報だけで実在の個人を特定することはできないはずです)。
  • コメントが投稿されたことをTwitter@YOCKOW_jpで報せます(※サーバエラーなどで報知できないことがあります)。
  • 一定時間内に連続してコメントを投稿することはできません。
  • 色んな意味でYOCKOWの独壇場です。