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

C言語(AIX)からの移植作業で問題となった事案を紹介

●バイトオーダー
コンピュータの内部ではデータは全て2進数で扱う仕組みになっている
2進数で 00000000 ~ 11111111 (16進数で 0x00~0xff)で表される単位、つまり8ビットを1バイト
コンピュータでデータをメモリに読み書きしたり、ディスクに読み書きするときには、1バイトを最小単位にして行う

例えば、0x12,0x34,0x56,0x78 という4つのデータがある。
これをメモリ中の0x1000番地から書き込む。

0x1000番地:0x12
0x1001番地:0x34
0x1002番地:0x56
0x1003番地:0x78

これよりも大きなサイズのデータ
例えば、0x12345678
これをメモリ中の0x1000番地から書き込む。

0x1000番地:0x12
0x1001番地:0x34
0x1002番地:0x56
0x1003番地:0x78

 

連続した4番地をひとかたまりのデータとして管理

 

世の中にはこのようなデータ格納方式を取らないものもある。

0x1000番地:0x78
0x1001番地:0x56
0x1002番地:0x34
0x1003番地:0x12

順番を逆転させて格納する方式がある。

このバイト並びの方式をエンディアン(Endian)と呼ぶ。
前者の、0x12(つまり桁の大きいほう)から順番に格納する方式をビッグエンディアン(Big Endian)
後者の、0x78(つまり桁の小さいほう)から順番に格納する方式をリトルエンディアン(Little Endian)

 


●CPUとエンディアン
エンディアンはCPUによって決まる。
PowerPCなどはビッグエンディアン。
Intel系などはリトルエンディアン。
MIPS や ARM、SHなど、どちらにもなれるプロセッサも存在していて、バイエンディアン。

 


●困ってたこと
メモリ上のデータの持ち方が変わっても特に問題なし

int a = 1;
(0x00000001)

・ビッグエンディアン
0x1000番地:0x00
0x1001番地:0x00
0x1002番地:0x00
0x1003番地:0x01

・リトルエンディアン
0x1000番地:0x01
0x1001番地:0x00
0x1002番地:0x00
0x1003番地:0x00


ビッグエンディアンが前提のコードで問題あり(バイト単位の比較)

int memcmp( const void *str1 , const void *str2, size_t len );
str1とstr2をlen文字分比較して等しい場合は0、
同様にstr1がstr2より大きい場合(str1>str2)は正の整数、
同様にstr1がstr2より小さい場合(str1<str2)は負の整数を返す。

0x00000001と0x00000100を比較

・ビッグエンディアン
0x1000番地:0x00
0x1001番地:0x00
0x1002番地:0x00
0x1003番地:0x01

0x1000番地:0x00
0x1001番地:0x00
0x1002番地:0x01
0x1003番地:0x00

・リトルエンディアン
0x1000番地:0x01
0x1001番地:0x00
0x1002番地:0x00
0x1003番地:0x00

0x1000番地:0x00
0x1001番地:0x01
0x1002番地:0x00
0x1003番地:0x00


●対策
typedef    struct    data
{
    unsigned char a[4];
    unsigned char b[4];
    unsigned char c[4];
} DATA;

ビッグエンディアンのように変換して比較処理
unsigned char tmp[12] = {
    a[3],
    a[2],
    a[1],
    a[0],
    b[3],
    b[2],
    b[1],
    b[0],
    c[3],
    c[2],
    c[1],
    c[0]};

既存の処理をあまり変えないように対応する


●余談
ビッグエンディアンとリトルエンディアンという単語は、『ガリバー旅行記』の中のエピソードに由来する。
第1部「小人国」(ガリバーが浜辺で小さい人たちに、たくさんの細いロープで縛り付けられている絵本を覚えている人も多いだろう)では、
卵を丸い方(大きい方)の端から割る人々 (Big Endians) と、尖った方(小さい方)の端から割る人々(Little Endians) との対立が描かれている。

スウィフトが書いた風刺小説「ガリバー旅行記」に登場する「ビッグ・エンディアンとリトル・エンディアン」は、
キリスト教のカトリック(旧教)とプロテスタント(新教)を指しています。
つまり、「ゆで卵の割り方のような”ささいな違い”」から争いが続いている状況を、スウィフトはガリバー旅行記として風刺していたのです。