エンディアン
エンディアン(endianness)は、複数のバイトなどを計算機のメモリ上に並べる順序の種類である。一般的な用語による表現ではバイトオーダ(byte order)、ないしそれを一部訳して日本語ではバイト順とも言う。
英語の「endian」という単語自体には元々は「配置方式」「並び順」といった意味はなかった(#語源を参照)。日本では総称として「エンディアン」と呼ぶことが多いが、英語でそれに相当する語はendianness(エンディアンネス)である。
その他、日付の表記において年・月・日をどの順序で記述するかの分類にも用いられる。
例えば、十六進法で表現すると1234ABCDという1ワードが4バイトのデータを、バイト毎に上位側(通常左側)から「12 34 AB CD」のように並べる順序はビッグエンディアン (big-endian)、下位側(通常右側)から「CD AB 34 12」のように並べる順序はリトルエンディアン (little-endian) である。その他に「34 12 CD AB」あるいは「AB CD 12 34」のように並べる方式もあり、ミドルエンディアン (middle-endian) などという。またこのミドルエンディアンの2つのうちの前者は、DECのPDP-11で使われていたことからPDPエンディアンなどとも呼ばれる。ミドルエンディアンは、後付けの拡張などが理由で現れるが、実例はそれほど多くはない。
一般にエンディアンと言えばバイト(オクテット)のそれを指していることが多いが、任意の長さのワードに対して考えることもでき、ビットに対しても言える(ただし、ビットに関しては、「ビッグ」「リトル」の順序に混乱がある場合があるようであり、MSB first / LSB first のような表現を使ったほうが安全ではある)。
ビッグエンディアンは、メモリ内にそのように並べた場合に、一般的なバイト単位で出力するダンプリストや、メモリ内の通常の文字列の場合と同様にして出力すると、人間が普段慣れている記法と同じ順序になるのでわかりやすいという利点がある。
一方、リトルエンディアンは例えば、バイト毎の並びを、256進法であるとして見た場合に、アドレス+0 にあるのが 2560 の桁、アドレス+1 にあるのが 2561 の桁といったように、数値の表現法と対応しているという整合性がある。また、データの送受信などにおける順番では、多倍長加算などで最下位から順番に計算したほうが繰上りの計算がしやすいこと、などとも相性がよい。
なお、ネットワーク機器などで、アドレスの上位で送り先のおおまかな識別ができる場合など、キャリアグレードルータなどではデータを受信しながら処理を始めてしまうといったものもあり、そういった場合はビッグエンディアンに利がある。
IBMのメインフレーム(および互換機)、モトローラのMC68000(および後継)、サン・マイクロシステムズのSPARCなどはビッグエンディアンを採用し、DECのVAX、インテルのx86などはリトルエンディアンを採用している。ARMアーキテクチャ、PowerPCなど、エンディアンを切り替えられるバイエンディアン (bi-endian) のプロセッサも存在する。
言語処理系などの仮想マシンの類では、プラットフォームに応じ使い分ける設計のものもあれば、片方に寄せる設計のものもある。例えば、Java仮想マシンはプラットフォームを問わずビッグエンディアンである。
エンディアンの相違は、単一あるいは同種のシステムに閉じた運用をする限りでは通常は問題にならない。それ以上のことをする場合の、問題が起こりやすい例を示す。
TCP/IPプロトコルスタックでは、ビッグエンディアンに統一しており、それをネットワークバイトオーダという。この分野では、それに対し、各コンピュータのエンディアンをホストバイトオーダという。
画像や音声などのバイナリファイルにおいても、異なるコンピュータ間の互換性を確保するため、通常はエンディアンが規定される。
Unicodeにおいても、構成要素が多バイトとなるエンコーディング(主にUTF-16)では、エンディアンが問題となる。そのため、バイト順マーク(Byte Order Mark、略語:BOM)と呼ばれる特殊なコード (U+FEFF) が予約されており、データの先頭にこれを付与することで、データを受け取る側がエンディアンを判別できるようになっている。BOMがない場合には、ビッグエンディアンだと決められている(→ UTF-16)。
ただし、復号側が以上のルールでエンディアンを判別する狭義のUTF-16とは別に、エンディアンを事前に一方に決定しているUTF-16BEとUTF-16LEが存在する。Windows上の文書における「Unicodeテキスト」は、BOMがない場合、UTF-16LE(リトルエンディアン)である。
32ビットの場合で、より詳細に示す。
すべての例は十六進法の表記で <tt>0A0B0C0D</tt> という値をメモリに格納した場合を示している。
例では最上位バイト (MSB) は <tt>0A</tt> となり、メモリ上では一番低いアドレスに保存され、次のバイト <tt>0B</tt> は続いて格納される。これは16進で左から右に読むのに似ている。
最上位に <tt>0A0B</tt> が保存され、続いて <tt>0C0D</tt> が保存される。
最下位バイト (LSB) は <tt>0D</tt> で、そのアドレスは一番低い。他のバイトはアドレス増加に追従する。
16ビットで格納されている最下位の値は <tt>0C0D</tt> で続いて <tt>0A0B</tt> が入る。
さらに、ミドルエンディアンまたはミックスドエンディアンと総称的に呼ばれることもある、さらに込み入ったバイトオーダもある(こういった「変」なものを扱う時は、どのような組合せなのか具体例での注意深い確認が欠かせない)。
著名な例としては、PDP-11における32ビットワードの扱い方がある。PDP-11では 0x0A0B0C0D が、最上位バイトから <tt>0B 0A 0D 0C</tt> という順に格納される。つまり、上位ハーフワード(16ビット)と下位ハーフワードとしてはビッグエンディアンで格納される。各ハーフワード内の上位下位の各オクテットはリトルエンディアンで格納される。PDP-エンディアンという別名がある。
PDP-11に32ビットワードを格納する場合
ARMアーキテクチャは32ビットワードを32ビットワードから2バイトに格納した場合、このエンディアンを生成することができる。
MIPSのELFファイル中に、64ビットワードを「上位32ビットはビッグエンディアン、下位32ビットはリトルエンディアン」で格納する、というフィールドがある。2016-07
C言語では共用体のtype-punningを使ってエンディアンを確かめることができる。ただし、標準規格2021-05では処理系定義とされている動作に依存している。
bytes.b4: 12345678
bytes.b2: 1234, 5678
bytes.b1: 12, 34, 56, 78
bytes.b4: 12345678
bytes.b2: 5678, 1234
bytes.b1: 78, 56, 34, 12
となる。
64ビット版の例:
エンディアンは、日付の年月日の表現の分類にも使われる。2021年4月12日を例に取ると、
年月日の順(2021/04/12) ビッグエンディアン Big-Endian (中国、日本、韓国など)
日月年の順(12/04/2021) リトルエンディアン Little-Endian (英国、フランス、ドイツ、イタリア、ロシアなど)
月日年の順(04/12/2021) ミドルエンディアン Middle-Endian (米国)
日付の国際規格であるISO 8601では、ビッグエンディアンのみが認められている。ただし、区切りの符号は、「/」ではなく、「-」でなければならない(例:2021-04-12)。
ビッグエンディアンとリトルエンディアンという語は、ジョナサン・スウィフトの風刺小説『ガリヴァー旅行記』の中のエピソードに由来する。ガリヴァー旅行記の第1部「小人国」では、ゆで卵を丸い方(大きい方)の端 (big end) から割る人々(Big Endians)と尖った方(小さい方)の端 (little end) から割る人々 (Little Endians) との対立が描かれている。
この語を計算機に転用したのはダニー・コーエンで、1980年4月1日に発表したジョークRFC"On Holy Wars and a Plea for Peace"(聖戦と平和の嘆願について)で初めて使用した。