リトルエンディアンとビッグエンディアン

回 1-5 道 1 数と論理と計算量

リトルエンディアンは、2 バイト以上の値をメモリに置くとき、一番下の桁のバイトを小さい番地から並べる決まりです。ビッグエンディアンはその逆で、一番上の桁のバイトから並べます。0x12345678 なら、リトルエンディアンでは 78 56 34 12、ビッグエンディアンでは 12 34 56 78 の順になり、読む側が並びを取り違えると 2018915346 のような別の値に化けます。

値そのものと、値をバイトに切って並べる順番を切り分けられるようになります。

なぜ同じ値が、逆の順に並ぶのか

2 バイト以上の値をバイトに切ってメモリに置くとき、上の桁から置くか下の桁から置くかは、機械ごとの決まりで、どちらも正しく動きます。この決まりをバイトオーダー (バイトの並び順) やエンディアンと呼びます。

たとえば 0x12345678 という値をファイルに書き、中身を 16 進数で 1 バイトずつ見ると、78 56 34 12 と逆向きに並んでいることがあります。書いた値は同じなのに、並びが逆に見えるのはなぜでしょうか。

手がかりは、メモリが 1 バイトごとに番地 (置き場所の番号) を振った棚だということです。4 バイトの値は 4 つの棚に分けて置くので、どの桁のバイトを一番小さい番地に置くかを決める必要があります。

ビットはスイッチのオンとオフで、8 個で 1 バイトになる図

エンディアンはどう決まっているのか

エンディアンは、値の一番上の桁のバイトと一番下の桁のバイトの、どちらを小さい番地に置くかの決まりです。値の大きさや意味は変わらず、置く順番だけが違います。

ビッグエンディアンとリトルエンディアンの違い

ビッグエンディアンは上の桁から、リトルエンディアンは下の桁から並べます。0x12345678 は 16 進数 2 桁ずつで 12、34、56、78 の 4 バイトに分かれ、12 が一番上の桁、78 が一番下の桁です。

番地ビッグリトル
01278
13456
25634
37812

ビッグエンディアンは、紙に数を書くときと同じ順なので、人が読みやすい並びです。リトルエンディアンは、番地を小さい方から読むと逆に見えますが、番地 0 にいつも一番下の桁がある、という揃い方をしています。

入れ替えるのは 1 バイト (16 進数 2 桁) の塊です。16 進数の 1 桁ずつを逆にした 87654321 にはなりません。下の図で、区切る単位をバイトと 4 ビットで切り替えると、結果が分かれます。

バイト順の入れ替えと4ビット反転

なぜ 2 つに分かれ、なぜその名前なのか

エンディアンの名前は、1980 年 4 月 1 日に Danny Cohen が書いた文書「On Holy Wars and a Plea for Peace」(IEN 137) が、ガリバー旅行記から借りたものです。物語では、卵を大きい端から割る人々 (Big-Endians) と小さい端から割る人々 (Little-Endians) が争います。Cohen は、どちらの端から並べるかの争いもそれと同じで、大事なのはどちらかに揃えることだと書きました。

2 つに分かれたのは、どちらにも理由があったからです。ビッグは人が読む順と同じで、リトルは番地 0 に一番下の桁があるので、下の 1 バイトや 2 バイトだけを読むときも同じ番地から読めます。

どの機械とどの通信がどちらか

今のパソコンの多くはリトルエンディアンで、ネットワークの決まりはビッグエンディアンです。Python の公式文書は、Intel の x86、AMD64 (x86-64)、Apple M1 をリトル、IBM z をビッグの例に挙げています。

場所並び
Intel x86、AMD64リトル
Apple M1リトル
Windows の ARM64リトル
IBM zビッグ
WebAssembly のメモリリトル
IP や TCP の頭の数ビッグ

IP の決まりを書いた RFC 791 は、2 バイト以上の数を送るときは一番上の桁のバイトから送ると定めています。そのため、ネットワークで送る並びをネットワークバイトオーダーと呼び、中身はビッグエンディアンです。ARM は作りの上では並びを切り替えられますが、Microsoft は Windows の ARM64 がリトルエンディアンで動くと書いています。

この頁の Python はブラウザの中の WebAssembly で動くので、リトルエンディアンの機械として振る舞います。

ファイルの形式は、形式ごとに決めている

ファイルの中の 2 バイト以上の数は、ファイルの形式の決まりに並びが書いてあり、機械ではなく形式に従います。PNG の画像は、2 バイト以上の整数をネットワークバイトオーダー (ビッグエンディアン) で書くと決めています。

文字でも、UTF-16 (1 字を 2 バイトか 4 バイトで表す文字コード) は並びの問題を持ちます。そこでファイルの頭に BOM (バイト順の印) を置き、FE FF ならビッグ、FF FE ならリトルと読み手に知らせます。UTF-8 は 1 バイトずつ順に読む作りなので、並びの問題がありません。

並びを入れ替えて変換する

並びの違う相手とやり取りするときは、送る前と読んだ後に、バイトの順を入れ替えます。C 言語では htonl (ホストの並びからネットワークの並びへ) と ntohl (その逆) という関数が使われ、Python では int.to_bytes と int.from_bytes に並びを渡します。並びを毎回明示すれば、どの機械で動かしても同じバイト列になります。

動かして確かめる

同じ値を 2 つの並びでバイトに切り、番地ごとに並べます。to_bytes(4, "big") は 4 バイトのビッグエンディアン、"little" はリトルエンディアンです。

動かす 同じ値を 2 つの並びで

python実行可能
出力

▶ 実行ボタンを押すと結果がここに表示されます

実行すると、次の通りに出ます

big    12 34 56 78
little 78 56 34 12
番地 0 12 78
番地 1 34 56
番地 2 56 34
番地 3 78 12

番地 0 には、ビッグでは一番上の桁の 12、リトルでは一番下の桁の 78 が入りました。4 バイトの中身は同じで、順番だけが逆です。

次に、いま動いている機械がどちらかを確かめます。sys.byteorder は機械の並びを返します。array に 4 バイトの整数を入れて取り出すと、機械の並びのままのバイト列が見えます。

動かす 自分の機械の並びを見る

python実行可能
出力

▶ 実行ボタンを押すと結果がここに表示されます

実行すると、次の通りに出ます

little
78 56 34 12
01 00
下の桁が番地 0

この環境はリトルなので、機械の並びで書いた 0x12345678 は 78 56 34 12 です。後半は判定のよくある書き方で、1 を 2 バイトで置き、番地 0 に 01 が来ればリトルです。

並びは、機械に任せずに決めることもできます。struct は値を決まった形のバイト列に詰める道具で、頭の < はリトル、> はビッグ、! はネットワークバイトオーダーを指します。

動かす 並びを決めて詰める

python実行可能
出力

▶ 実行ボタンを押すと結果がここに表示されます

実行すると、次の通りに出ます

<I 78 56 34 12
>I 12 34 56 78
!I 12 34 56 78

! と > は同じ並びです。ネットワークバイトオーダーはビッグエンディアンだからです。I は 4 バイトの符号なしの整数を表します。

最後に、並びの入れ替えを関数にします。リトルで切ったバイト列を、ビッグとして読み直すだけです。

動かす 並びを入れ替える

python実行可能
出力

▶ 実行ボタンを押すと結果がここに表示されます

実行すると、次の通りに出ます

0x78563412
0x12345678

2 回入れ替えると元に戻ります。リトルエンディアンの機械で htonl と ntohl が同じ入れ替えで済むのはこのためです。ビッグエンディアンの機械では、元からネットワークと同じ並びなので、どちらも何もしません。

並びを取り違えると何が起きるか

書いた側と読む側の並びが違うと、エラーは出ずに、値が黙って別の値に化けます。バイト列には、どちらの並びで書いたかの情報が入っていないからです。

読み違えた値は、桁ごと入れ替わる

ビッグで書いたバイト列を、リトルとして読んでみます。

動かす ビッグで書きリトルで読む

python実行可能
出力

▶ 実行ボタンを押すと結果がここに表示されます

実行すると、次の通りに出ます

0x12345678 305419896
0x78563412 2018915346
00 00 00 01
16777216

305419896 は 2018915346 に化けました。1 は 4 バイトのビッグで 00 00 00 01 と並び、リトルとして読むと 0x01000000 で 16777216 です。件数が 1 件のはずのデータが、1677 万件に見えます。

通信の番号 (ポート) でも同じことが起きます。

動かす 8080 を読み違える

python実行可能
出力

▶ 実行ボタンを押すと結果がここに表示されます

実行すると、次の通りに出ます

1f 90
36895

8080 は 16 進数で 1F90 なので、ビッグでは 1F 90 と並びます。これをリトルとして読むと 0x901F で、36895 番に化けます。接続先の番号がずれれば、つながらないか、別の物につながります。

文字にも並びの取り違えがある

UTF-16 の文字も、並びを取り違えると別の字に化けます。

動かす あ を UTF-16 で読み違える

python実行可能
出力

▶ 実行ボタンを押すと結果がここに表示されます

実行すると、次の通りに出ます

30 42
42 30
e3 81 82
䈰 0x4230

「あ」の番号は 0x3042 で、ビッグでは 30 42、リトルでは 42 30 です。ビッグで書いた 30 42 をリトルとして読むと 0x4230 になり、まったく別の漢字が出ました。UTF-8 の E3 81 82 は、どの機械でも同じ並びです。

崩れる前提をまとめると、次の通りです。

  • 書いた機械と読む機械の並びが同じ、という前提。ファイルや通信で別の機械に渡ると崩れる
  • 1 と 0 だけの試験の値で並びの誤りが見つかる、という前提。0 は並びを逆にしても 0 なので見つからない
  • 1 バイトのデータに並びの問題は無い、という前提は正しい。並びが効くのは 2 バイト以上の値だけ

仕事でどう確かめるか

仕事では、書く側と読む側の並びを仕様で決め、どちらから見ても桁が分かる値で試験します。

1 つ目は、並びを毎回明示することです。Python の struct なら < か > か ! を必ず付け、機械の並びになる @ や付け忘れを避けます。ファイルや通信の形式の仕様に並びが書いてあるかも確かめます。

2 つ目は、試験の値を選ぶことです。0、1、0x01010101 のように逆にしても同じか似た値ではなく、0x12345678 のように 4 バイトが全部違う値を書き、読んだ値が一致するかを見ます。

3 つ目は、バイトの中身を目で見ることです。Python なら data[:16].hex(" ")、端末なら xxd や hexdump で頭のバイトが並びます。並びの違うマイコンへプログラムを移すときも、通信やファイルに出る値をこうして照らします。

関わる実例

並びの取り違えは、値が黙って化けるので、守りの仕組みをすり抜ける穴にもなります。

Apache の mod_access の穴 CVE-2003-0993 (NVD の公開 2004 年 3 月 29 日)

米国の脆弱性データベース NVD によると、Web サーバーの Apache 1.3 (1.3.30 より前) の mod_access は、ビッグエンディアンの 64 ビットの機械で動かすと、網の印 (ネットマスク) を付けずに IP アドレスで書いた許可と拒否の決まりを正しく読めませんでした。外から、決めたはずのアクセスの制限をすり抜けられるおそれがありました。

崩れた前提は「どの機械でも、アドレスのバイトは同じ並びで読める」です。リトルエンディアンの機械では正しく動いていたので、並びの違う機械に移して初めて表に出ました。並びの違う機械で同じ試験を回すことが、この種の誤りを見つける近道です。

よくある問い

リトルエンディアンのメリットは何ですか

リトルエンディアンでは番地 0 にいつも一番下の桁が来るので、4 バイトの値の下の 1 バイトや 2 バイトだけを読むとき、同じ番地から読めます。足し算のように下の桁から順に計算する処理とも順番が揃います。一方、16 進数で中身を見ると逆に見えるので、人には読みにくいところがあります。

自分のパソコンがどちらかを確かめるにはどうしますか

Python なら import sys のあと sys.byteorder を表示すると、little か big が出ます。Python の公式文書によると、Intel の x86、AMD64、Apple M1 はリトルエンディアンです。上の「自分の機械の並びを見る」のコードも、そのまま確かめに使えます。

ネットワークバイトオーダーとは何ですか

ネットワークバイトオーダーは、IP や TCP などの通信で 2 バイト以上の数を送るときの並びで、ビッグエンディアンです。IP の決まりの RFC 791 が、数を一番上の桁から送ると定めています。リトルエンディアンの機械は、送る前と受けた後に並びを入れ替えます。

Java や C ではどう変換しますか

C 言語では、htonl や ntohl (4 バイト)、htons や ntohs (2 バイト) でホストの並びとネットワークの並びを入れ替えます。Java は値をビッグエンディアンで読み書きするのが既定で、リトルエンディアンのデータは ByteBuffer の order(ByteOrder.LITTLE_ENDIAN) で並びを指定して読みます。どの言語でも、並びを明示して読むのが安全です。

確認クイズ

答えだと思う選択肢を押すと、その場で正誤と理由が開きます。4 問すべてに正しく答えると、この回は修了で、石が緑に変わります (この端末のブラウザに残ります)。間違えた問いは、あとから解き直せます。

1 問目

0x12345678 をリトルエンディアンでメモリに置くと、番地 0 から順にどう並びますか。

2 問目

このコードを動かすと何が出ますか。

1 をリトルで読む

b = (1).to_bytes(2, "big")
n = int.from_bytes(b, "little")
print(n)

3 問目

ネットワークバイトオーダーについて正しいのはどれですか。

4 問目

並びの取り違えを見つける試験の値として、一番よいのはどれですか。

説明課題

次のことを、自分の言葉で 3 行にまとめてください。書いたら、下の模範解答を開いて比べてください。

  • 0x12345678 が、ある機械では 12 34 56 78、別の機械では 78 56 34 12 と並ぶ理由
  • 並びを取り違えたとき何が起き、どう防ぐか

模範解答

自分の説明を書いてから開いて、比べてください。

この回の先の一歩

バイナリのファイルや通信のデータを読む仕事では、バイトの並び順の取り違えが、値が化ける不具合の原因になります。いまの自分が転職までの道のどの段にいるかは、転職診断で確かめられます。

もっと深く

この回の続きを、ゆめさくのコースの章や道具で深められます。頁の中の確認クイズに答えたあと、手を動かす量を増やしたいときに使ってください。

一次資料

どれも 2026年10月26日に開いて、題と中身を確かめました。

次へ

前の回 1-4論理と真理値表AND、OR、NOT、ド・モルガン準備中
次の回 1-6Base64 の仕組み64 字の表、= の詰め物、長さ 4/3

道 1 数と論理と計算量の回

  1. 1-12 進数と 16 進数桁の重み、変換、表せる範囲頁で読む
  2. 1-2文字コードと文字化けUnicode、UTF-8、Shift_JIS、BOM頁で読む
  3. 1-3計算量を数えるBig-O、ループの回数頁で読む
  4. 1-4論理と真理値表AND、OR、NOT、ド・モルガン準備中
  5. 1-5リトルエンディアンとビッグエンディアンバイトの並び順、ネットワーク、ファイルこの回
  6. 1-6Base64 の仕組み64 字の表、= の詰め物、長さ 4/3頁で読む
  7. 1-7情報量とハフマン符号化ビット、確からしさ、圧縮頁で読む
  8. 1-8チューリングマシンと停止問題テープ、状態、計算できない問題頁で読む

道 1 の頁へ戻るほかの道を見る