エンディアン: ビッグエンディアンとリトルエンディアンのバイト順序
ビッグエンディアンとリトルエンディアンのバイト順序を理解。マルチバイト値がメモリにどう格納されるか、クロスプラットフォームコードでなぜ重要かを解説します。
詳細な説明
エンディアンは、マルチバイト値のバイトがメモリに格納される順序を表します。一見単純な概念ですが、クロスプラットフォームソフトウェア、ネットワークプログラミング、バイナリファイル解析における主要なバグの原因です。
ビッグエンディアン(ネットワークバイトオーダー):
最上位バイトが最も低いメモリアドレスに格納されます。数値 0x12345678 は以下のように格納されます:
Address: 0x00 0x01 0x02 0x03
Value: 0x12 0x34 0x56 0x78
これは人間が数値を書く方法(最上位桁が先)と一致します。TCP/IP ネットワークプロトコルはビッグエンディアンを使用するため、「ネットワークバイトオーダー」とも呼ばれます。
リトルエンディアン(Intel バイトオーダー):
最下位バイトが最も低いメモリアドレスに格納されます。同じ 0x12345678 は以下のように格納されます:
Address: 0x00 0x01 0x02 0x03
Value: 0x78 0x56 0x34 0x12
ほとんどの最新 CPU(x86、x86-64、多くの ARM 構成)はリトルエンディアンを使用します。
リトルエンディアンが存在する理由:
リトルエンディアンは特定のハードウェア操作を簡素化します。32ビット整数を16ビット整数にキャストする場合、値はすでに同じメモリアドレスにあるため、ポインタの調整が不要です。加算も最下位バイトから自然に上位へ進行します。
エンディアンが問題を引き起こす場面:
- ネットワーク通信: Intel マシン(リトルエンディアン)から SPARC マシン(ビッグエンディアン)に送信されたデータは、バイトスワップしないと文字化けします。
htonl()やntohl()などの関数がこれを処理します。 - バイナリファイル形式: ファイル形式はエンディアンを指定しています。BMP ファイルはリトルエンディアン。TIFF ファイルにはエンディアンマーカーが含まれます。間違ったバイト順でファイルを読むと無意味な値になります。
- Hexdump 分析: x86 システムのメモリの Hexdump を読む際、32ビット整数
0x00000001は01 00 00 00として表示され、00 00 00 01ではありません。
コードでエンディアンを検出する:
JavaScript: new Uint8Array(new Uint32Array([1]).buffer)[0] === 1 はリトルエンディアンシステムで true を返します。Python: import sys; sys.byteorder は 'little' または 'big' を返します。
ユースケース
組み込みシステムエンジニアは、リトルエンディアンの ARM プロセッサとビッグエンディアンのネットワークプロトコルや周辺機器間の通信ドライバを書く際に、エンディアン変換を処理します。