トップC/C++ > リトル・エンディアンとビッグ・エンディアン

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

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

2バイト以上のデータ幅を持つ数値データをメモリやファイルに記録したり転送するとき、 最下位のバイトから順番に記録・転送する方式をリトル・エンディアン(little endian)、 最上位のバイトから順番に行う方式をビッグ・エンディアン(big endian)とよぶ。 Intel社のマイクロプロセッサではリトル・エンディアン、 Motorola社のプロセッサはビッグ・エンディアンで記録する。

Intelプロセッサの動作確認

次のプログラムは、4バイト整数 0x41424344 を変数 n に格納し、 変数アドレス(4バイト整数が格納された先頭番地)を p にセットしている。 従って、p[0] が先頭バイト、p[3] が末尾のバイトとなる。

void main() {
    int n = 0x41424344;
    char *p = (char*)&n;
    printf("n=%x   %02x %02x %02x %02x\n", n, p[0], p[1], p[2], p[3]);
    printf("%.4s\n", p);
}

実行結果を下に示す。"%x" で出力すると 41424344 であるが、 メモリには先頭から順に 44 43 42 41 が格納されていることに注意を要する。 0x41, 0x42, 0x43, 0x44 は英字 A, B, C, D のアスキーコードに当たる。 このため、4バイト整数を4バイトの文字列と考えて印字すると DCBA となることが確認できる。

MCC(自作Cコンパイラ)では、機械語コードをファイルに書き込む直前まで、 16進表記を使っている。 アセンブリ言語生成では、"%x" で数値を文字列に変えて出力している。 この方が、後で、strtoul(p, NULL, 16)関数で、16進表記の文字列を 数値に戻すのが楽なためである。 すなわち、途中はビッグ・エンディアンで、 出力直前ではリトル・エンディアンに直している。 これが、プログラムを分かりにくくしている面がある。 リトル・エンディアン方式と相性の悪い sprintf, strtoul の使用を少しずつ減らしている。

c:\MH\www\mcc\doc2012>endian
n=41424344   44 43 42 41
DCBA

リトルエンディアンで 32bit整数と文字列の比較

最初の4バイトが整数のファイルと長さ3の文字列(末尾の'\0'を含めると4バイト)のファイルがある。 どのような条件下では両者が区別できるだろうか?

英小文字のASCIIコードは 0x61〜0x7a、大文字が 0x41〜0x5a である。 文字列を "abc" とすると 61, 62, 63, 0 である。 これを 4バイト整数とみると 0x636261 である。