エンディアン
この記事には独自研究が含まれているおそれがあります。 |
エンディアン(英: 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)では、エンディアンが問題となる。そのため、バイト順マーク[1](英: Byte Order Mark、略語:BOM)と呼ばれる特殊なコード (U+FEFF) が予約されており、データの先頭にこれを付与することで、データを受け取る側がエンディアンを判別できるようになっている。BOMがない場合には、ビッグエンディアンだと決められている(→ UTF-16)。
ただし、復号側が以上のルールでエンディアンを判別する狭義のUTF-16とは別に、エンディアンを事前に一方に決定しているUTF-16BEとUTF-16LEが存在する。Windows上の文書における「Unicodeテキスト」は、BOMがない場合、UTF-16LE(リトルエンディアン)である。
例
32ビットの場合で、より詳細に示す。
すべての例は十六進法の表記で 0A0B0C0D という値をメモリに格納した場合を示している。
ビッグエンディアン
- 8ビットで1ずつアドレスが増加する場合
アドレス増加 → | |||||
0A | 0B | 0C | 0D |
例では最上位バイト (MSB) は 0A となり、メモリ上では一番低いアドレスに保存され、次のバイト 0B は続いて格納される。これは16進で左から右に読むのに似ている。
- 16ビットで1ずつアドレスが増加する場合
アドレス増加 → | |||||
0A0B | 0C0D |
最上位に 0A0B が保存され、続いて 0C0D が保存される。
リトルエンディアン
- 8ビットで1ずつアドレスが増加する場合
アドレス増加 → | |||||
0D | 0C | 0B | 0A |
最下位バイト (LSB) は 0D で、そのアドレスは一番低い。他のバイトはアドレス増加に追従する。
- 16ビットで1ずつアドレスが増加する場合
アドレス増加 → | |||||
0C0D | 0A0B |
16ビットで格納されている最下位の値は 0C0D で続いて 0A0B が入る。
ミドルエンディアン
さらに、ミドルエンディアンまたはミックスドエンディアンと総称的に呼ばれることもある、さらに込み入ったバイトオーダもある(こういった「変」なものを扱う時は、どのような組合せなのか具体例での注意深い確認が欠かせない)。
著名な例としては、PDP-11における32ビットワードの扱い方がある。PDP-11では 0x0A0B0C0D が、最上位バイトから 0B 0A 0D 0C という順に格納される。つまり、上位ハーフワード(16ビット)と下位ハーフワードとしてはビッグエンディアンで格納される。各ハーフワード内の上位下位の各オクテットはリトルエンディアンで格納される。PDP-エンディアンという別名がある。
- PDP-11に32ビットワードを格納する場合
アドレス増加 → | |||||
0B | 0A | 0D | 0C |
ARMアーキテクチャは32ビットワードを32ビットワードから2バイトに格納した場合、このエンディアンを生成することができる。 MIPSのELFファイル中に、64ビットワードを「上位32ビットはビッグエンディアン、下位32ビットはリトルエンディアン」で格納する、というフィールドがある[2]。[信頼性要検証]
エンディアンの確認
C言語
C言語では共用体のtype-punningを使ってエンディアンを確かめることができる。ただし、標準規格[どれ?]では処理系定義とされている動作に依存している[3][4]。
#include <stdint.h>
#include <stdio.h>
int main(int argc, char **argv)
{
union
{
uint32_t b4; /* 4 bytes */
uint16_t b2[2]; /* 2 bytes x 2 */
uint8_t b1[4]; /* 1 byte x 4 */
} bytes;
bytes.b4 = 0x12345678;
printf("bytes.b4: %08X\n", bytes.b4);
printf("bytes.b2: %04X, %04X\n", bytes.b2[0], bytes.b2[1]);
printf("bytes.b1: %02X, %02X, %02X, %02X\n", bytes.b1[0], bytes.b1[1], bytes.b1[2], bytes.b1[3]);
return 0;
}
32ビット機ビッグエンディアンでの出力結果
bytes.b4: 12345678 bytes.b2: 1234, 5678 bytes.b1: 12, 34, 56, 78
32ビット機リトルエンディアンでの出力結果
bytes.b4: 12345678 bytes.b2: 5678, 1234 bytes.b1: 78, 56, 34, 12
となる。
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
int main(int argc, char **argv)
{
union
{
uint64_t b8; /* 8 bytes */
uint32_t b4[2]; /* 4 bytes x 2 */
uint16_t b2[4]; /* 2 bytes x 4 */
uint8_t b1[8]; /* 1 byte x 8 */
} bytes;
bytes.b8 = UINT64_C(0x123456789ABCDEF0);
printf("bytes.b8: %16" PRIX64 "\n", bytes.b8);
printf("bytes.b4: %08" PRIX32 ", %08" PRIX32 " \n", bytes.b4[0], bytes.b4[1]);
printf("bytes.b2: %04" PRIX16 ", %04" PRIX16 ", %04" PRIX16 ", %04" PRIX16 " \n", bytes.b2[0], bytes.b2[1], bytes.b2[2], bytes.b2[3]);
printf("bytes.b1: %02" PRIX8 ", %02" PRIX8 ", %02" PRIX8 ", %02" PRIX8 ", %02" PRIX8 ", %02" PRIX8 ", %02" PRIX8 ", %02" PRIX8 " \n",
bytes.b1[0], bytes.b1[1], bytes.b1[2], bytes.b1[3], bytes.b1[4], bytes.b1[5], bytes.b1[6], bytes.b1[7]);
return 0;
}
日付の方式での使い方
エンディアンは、日付の年月日の表現の分類にも使われる[7]。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"[8][9](聖戦と平和の嘆願について)で初めて使用した。
脚注
- ^ Unicode Terminology English - Japanese, B, Unicode, Inc.
- ^ https://gist.github.com/rui314/b3a5b107ce20c2d54f345216cc15a980
- ^ 標準規格では、共用体を使って、同じ領域を異なる型としてアクセスした場合は処理系定義である。ポインタを使ってアクセスするのは、strict aliasing rule違反により未定義であるので良くない。ここで示しているコードは、インテルCPUのシステムでVisual C++ 2013、GCC 4.9.3で動作確認済み。
- ^ EXP39-C. 適合しない型のポインタを使って変数にアクセスしない
- ^ プログラムちょい替え(3)Endian確認プログラム、64bitを追加(C言語)。, docker(84) - Qiita
- ^ Intel Core i5プロセッサ、clang-1000.11.45.5 / Docker gcc 6.3.0 20170516 での確認例が記載されている。
- ^ Date Format Variations: Little-Endian, Middle-Endian, Big-Endian proofreading academy
- ^ IEN 137 (1 April 1980) http://www.ietf.org/rfc/ien/ien137.txt これ以前の用語が「byte order」であったことなどもわかる
- ^ D. Cohen. 1981. On Holy Wars and a Plea for Peace. Computer 14, 10 (October 1981), 48-54. doi:10.1109/C-M.1981.220208