エンディアン

出典: フリー百科事典『ウィキペディア(Wikipedia)』

リトルエンディアン から転送)

エンディアン (endianness) とは、多バイトデータ(即ち基本情報記憶単位を超えるデータ)をメモリ上に配置する方式の種類のこと。エンディアンネスバイトオーダ (byte order) ともいう。

日本では「エンディアン」という呼称が広く使われているが、endian という単語自体には「配置方式」「並び順」といった意味はない。(#語源)

目次

[編集] 概要

例えば16進数で 0x1234ABCD という4バイトのデータを、データの上位バイトからメモリに「12 34 AB CD」と並べる方式をビッグエンディアン (big endian)、データの下位バイトから「CD AB 34 12」と並べる方式をリトルエンディアン (little endian) という。その他に「34 12 CD AB」あるいは「AB CD 12 34」のように並べる方式もあり、ミドルエンディアン(middle endian)、あるいはDECPDP-11で使われていたことからPDPエンディアンなどと呼ばれるが、現在ではほとんど見られない。

ビッグエンディアンは人間にとって直観的にわかりやすいという利点があり、一方リトルエンディアンはコンピュータにとって処理しやすい(多倍長加算の起点は最下位バイトであることなど)という利点がある。

IBM系のメインフレーム/汎用機、SunSPARCMotorolaMC68000等は「ビッグエンディアン」を採用し、インテルx86系などは「リトルエンディアン」を採用している。ARMアーキテクチャCPUTransmeta社のCrusoeHewlett-Packard社のPA-RISCPowerPCなど、エンディアンを切り替えられるバイエンディアン (bi-endian) のものも存在する。ただし稼動CPUを問わず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(リトルエンディアン)である。

[編集] メモリに0x0A0B0C0Dを記憶した場合のサンプル

それぞれの節の図は一番一般的な32ビット機のエンディアンです。必ずこれらのフォーマットを使う保障はありませんし、実際幾つかの例外があります。

すべてのサンプルは0x0A0B0C0Dをメモリに格納した場合を参照しています。

[編集] ビッグエンディアン

  • 8bitで1づつアドレスが増加する場合:
アドレス増加  →
... 0x0A 0x0B 0x0C 0x0D ...

サンプルでは最上位ビット (MSB) は0x0Aとなり、メモリ上では一番低いのアドレスに保存され、次のバイト0x0Bは続いて格納される。これは16進で左から右に読むのに似ている。

  • 16bitで1づつアドレス増加する場合
アドレス増加  →
... 0x0A0B 0x0C0D ...

最上位に0x0A0Bが保存され、続いて0x0C0Dが保存される。

[編集] リトルエンディアン

    • 8bitで1づつアドレスが増加する場合:
アドレス増加  →
... 0x0D 0x0C 0x0B 0x0A ...

最下位ビット(LSB)は0x0Dで、そのアドレスは一番低い。他のバイトはアドレス増加に追従する。

  • 16bitで1づつアドレス増加する場合
アドレス増加  →
... 0x0C0D 0x0A0B ...

16ビットで格納されている最下位の値は0x0C0Dで続いて0x0A0Bが入る。

  • バイトアドレスが右から左に増加する場合:

16ビットで格納されている場合、上述しているように逆からになるが、リトルエンディアンの場合、左に向かって書くと良いからである。もしこの方法で記載した場合、ちょっとしたセンスが必要で、

←  アドレス増加
... 0x0A 0x0B 0x0C 0x0D ...

となる。 最下位ビット(LSB)は0x0Dとなり、一番低いアドレスとなる。他のバイトはアドレス増加に追従する。

←  アドレス増加
... 0x0A0B 0x0C0D ...

最下位の16ビットは0x0C0Dとなり次に0x0A0Bとなる。 しかしながらもしこのようにメモリが左に増加するするように表示するとUnicode若しくはASCIIテキストを表示すると普通に表示する場合の逆(左から右)となる。たとえば"XRAY"をリトルエンディアン用記法で表現すると

←  アドレス増加
... "Y" "A" "R" "X" ...

このメモリ配列とバイナリデータとの衝突はリトルエンディアンに基本的に備わっているものであるが、この衝突は左から右に書かれる言語でだけで起きる(例えばインドヨーロッパ語族の英語(ローマン)フランス語(ローマン)ロシア語(クリル文字)やヒンディー語(デーバナーガリー文字))。右から左に書く言語(アラビア語、ヘブライ語)はバイナリでも衝突はおきず、手際よくアドレスを左に向けて増加できる。(逆に、右から左に書く言語はビッグエンディアンシステムで衝突が起きる)

[編集] ミドルエンディアン

さらに他のアーキテクチャでは、ミドルエンディアン若しくはミックスドエンディアンと一般的には呼ばれるさらに込み入ったバイトオーダもある。例えばPDP-11など、32ビットワードを最上位ビットから最初2番目のバイトを最初に、次に1番目、次に4番目、最後に三番目を入れる。

  • PDP-11に32ビットワードを格納する場合
アドレス増加  →
... 0x0B 0x0A 0x0D 0x0C ...

最上位ハーフ(16ビット)と次のハーフ(16ビット)がビッグエンディアンで画格納され、しかしながらそれぞれの格納された先がリトルエンディアンと解釈できる事に注意してください。これはPDP-エンディアンと知られている。

ARMアーキテクチャは32ビットワードを32ビットワードから2バイトに格納した場合このフォーマットを提供できる。

[編集] C言語

C言語若しくはC++ではUnion、ポインタ等を使ってエンディアンを確かめることが出来る。逆に言えば使用環境に依存するプログラムになってしまうとも言える。以下に環境依存のプログラムを示す。[2]

#include<stdio.h>
union tag_uEndian
{
int in;			/* 4Byte	*/
unsigned short sh[2];	/* 2Byte×2	*/
unsigned char ch[4];	/* 1Byte×4	*/
};
int main()
{
	union tag_uEndian En;
	En.in = 0x12345678;
	printf("INPUT is %x\n",En.in);
	printf("short is %x,%x\n",En.sh[0],En.sh[1]);
	printf("char is %x,%x,%x,%x\n",En.ch[0],En.ch[1],En.ch[2],En.ch[3]);
 
	return 0;
}

32ビット機ビッグエンディアンでの出力結果

INPUT is 12345678
short is 1234,5678
char is 12,34,56,78

32ビット機リトルエンディアンでの出力結果

INPUT is 12345678
short is 5678,1234
char is 78,56,34,12

となる。

[編集] 語源

ビッグエンディアンリトルエンディアンという単語は、ジョナサン・スウィフトの風刺小説『ガリヴァー旅行記』の中のエピソードに由来する。ガリバー旅行記の第1部「小人国」では、卵を丸い方(大きい方)の端から割る人々 (Big Endians) と尖った方(小さい方)の端から割る人々 (Little Endians) との対立が描かれている。

[編集] 脚注

  1. ^ Unicode Terminology English - Japanese, B, Unicode, Inc.
  2. ^ ただしC89準拠。またC99完全準拠ではないがVC2008C++Express Edition,GCC3.4.5-20060117-3で動作確認済み。またUnionの項目がunsignedになっているのは負の数になってint長になるのを防ぐため。また"En.ch[0]"を"En.ch[0] & ff"又は"(unsigned)En.ch[0]"としても良い。

[編集] 関連項目

[編集] 外部リンク