今日は、重要なコンピュータの概念について話す。おそらく皆さんは聞いたことがあるが、あまり深く掘り下げていないものの一つであるビッグエンディアンとリトルエンディアン(Endianness)だ。

一、概念
ビッグエンディアンとリトルエンディアンは、複数バイトのデータのメモリ配列順序を指す。これを説明するのは少し抽象的で、図を使って説明すると分かりやすい。
メモリは一列の部屋のように考える。各バイトは一つの部屋で、各部屋には番地(メモリアドレス)があり、0番から始まり、その後1番、2番……と続く。

0番目のバイトのアドレスは小さいので、低メモリと呼ばれる。3番目のバイトのアドレスは大きいので、高メモリと呼ばれる。
今、ある数値abcdをこれらの部屋に入れる必要がある。各部屋には一つの数字を入れる。その場合、二つの方法がある。
第一种方法は、第一位aを低アドレス(0番地)に配置し、最後のdを高アドレス(3番地)に配置します。

のような配置は「ビッグエンディアン」(ビッグエンディアン、略称BE)と呼ばれ、大きな端が先に来ることを意味し、aがabcdの大きな端(最も重要な数値)です。
もう一方の配置方法は、最初のaを高アドレス(3番地)に配置し、最後のdを低アドレス(0番地)に配置することです。

この配置は「リトルエンディアン」(リトルエンディアン、略称LE)と呼ばれ、小さな端が先です。dが先にあります。
ビッグエンディアンとリトルエンディアンは合せてバイトオーダーと呼ばれ、これらの名前は18世紀のイギリスの小説『ガリフォード・トリロジー』に由来します。ある国が二つの派閥に分かれ、一派は卵を大きな頭から食べるべきだと考え、「ビッグエンディアン派」と呼ばれ、もう一派は卵を小さな頭から食べるべきだと考え、「リトルエンディアン派」と呼ばれました。二つの派閥は互いに譲り合わず、誰もが相手を説得できず、最終的には戦争さえ起こりました。

二、読みやすさ
人間にとって、異なるバイトオーダーの読みやすさは異なります。大部分の国では、左から右へと読む習慣があります。

ビッグエンディアンでは、最高位が左に、最低位が右にあり、読みやすいです。したがって、これらの国の人々にとって、左から右へと読むビッグエンディアンの読みやすさがより良いです。
しかし現実には、右から左へと読むリトルエンディアンは読みにくいですが、より広く使われています。x86とARMの这两种CPUアーキテクチャがリトルエンディアンを採用しているのは、なぜでしょうか?
または別の問い方をすれば、2つの異なるバイト順序が共存する理由は何か。1種類のみを使用する規定を統一すれば、より便利ではないか?
その理由は、それぞれが独自の適用シーンを持っているからです。特定のシーンではビッグエンディアンが有利で、他のシーンではリトルエンディアンが有利です。以下ではそれぞれを詳細に分析します。
三、奇偶性のチェック
リトルエンディアンが最も明確な利点を提供するのは、奇偶性のチェックです。つまり、個位を確認することで、ある数が奇数か偶数かを判断します。

例えば123456を考えてみましょう。ビッグエンディアンでは左から右に並び、コンピュータは最後の桁の個位まで読み取らなければならず6、それが偶数であることを確認できません。
一方、リトルエンディアンでは右から左に並び、個位が最初の位置にあります。したがって、最初の位置を1度だけ読み取るだけで、それが偶数であることがわかります。
四、符号のチェック
似たなシナリオは符号の確認で、数が正数か負数かを確定することです。

ビッグエンディアンの符号ビットは左端の最初のビットにあり、リトルエンディアンの符号ビットは右端の最後のビットにあります。したがって、ビッグエンディアンには利点があり、最初のビットを見るだけで負数かどうかを知ることができます。
五、大小の比較
次の操作は大小の比較です。現在、3つの数字があり、大小を比較する必要があります:43662576、594、2。

上の図はビッグエンディアンで並べられており、左から右に並べられているので、3つの数字は右端の個位で揃っています。比較する際、コンピューターは各数字のすべてのビットを読み取らなければならず、個位まで読み取った後で比較します。
リトルエンディアンに変更すると、以下の並べ方になります。

リトルエンディアンは右から左に並べられており、3つの数字は最初のビットで揃っています。コンピューターはすべてのビットを読み取る必要がなく、どの数字が次のビットを読めなかったら、それが最小です。例えば、2 この数字には第二位がありませんから、第二位を読んだ時点で最小であることがわかります。
そのため、比較する際にはリトルエンディアンの方が有利です。
六、乗算
次に、乗算操作を見てみましょう。
乗算は各位で掛け算を行い、各ループで進位を行います。

上の図はビッグエンディアンの24165が3841に掛けたものです。ビッグエンディアンの乗算では左に進位するので、左側に拡張し、各ループの結果が出るまで(上の例では四回)待ってから合計してメモリに統一書き込みます。
もしリトルエンディアンの乗算に変更すると、次のループの結果を待つ必要がなくなり、各ループで直接メモリに書き込むことができます。

上の図はリトルエンディアンの24165が3841に掛けたものです。リトルエンディアンの乗算では右に進位するので、右側に拡張し、左側の境界は変わらず、各ループの結果をメモリに書き込んだ後は移動する必要がなくなり、後で変更する場合は対応するビットだけを変更すればよいです。
そのため、リトルエンディアン方式の乗算には明らかな利点があります。
七、任意精度整数
前の例の下位から計算する特性は、任意精度整数に特に役立ちます。任意精度整数は大整数とも呼ばれ、任意のサイズの整数を格納できます。
その内部実装では、整数を小さな単位に分け、通常は uint32(符号なし32ビット整数)または uint64(符号なし64ビット整数)で順番に組み合わせています。

ビッグエンディアンの場合、最初の u64 がこの整数の最大の部分になります。演算中に値が変わった場合、キャリーが発生すると、その後のすべてのビットを移動して書き換える必要があります。リトルエンディアンではキャリーが発生しても、すべてのビットを移動する必要はありません。
リトルエンディアンのもう一つの利点は、バイト単位の演算が下位から始まる場合(例えば乗算や加算)、左から右へ順番に u64 を演算し、一つ前を計算した後に次のものを読み込むことができる点です。ビッグエンディアンではできず、数全体を読み込んでから演算する必要があります。
八、型の変更
最後の例は、C言語にはキャスト操作があり、変数のデータ型を強制的に変更できる。例えば、32ビット整数を強制的に16ビット整数に変えることができる。

上の図では、32ビット整数0x00000001を16ビット整数0x0001に変更し、ビッグエンディアンでは前の2バイトを切り取る。この時、このアドレスを指すポインタは2バイト後ろに移動しなければならない。
リトルエンディアンではこの問題はない。後ろの2バイトを切り取るため、最初のアドレスは変わらないので、ポインタは移動する必要がない。
九、まとめ
以上をまとめると、ビッグエンディアンとリトルエンディアンのそれぞれの利点は以下の通りである。
ビット単位の演算が必要な場合、または個位から始まる演算が必要な場合、リトルエンディアンが有利である。逆に、演算が高位に限定されている場合、またはデータの読みやすさが重要な場合、ビッグエンディアンが有利である。
十、参照リンク
- エンディアンについて、カール・ステナルド
(終)












