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