Kodama's home / tips.

Big Endian と Little Endian の判別

Big Endian(ビッグ エンディアン), Little Endian(リトル エンディアン) とは?

数値のメモリーへの格納方法で, 数値の上位桁がメモリーの下位にあるような場合に big endian と云い, 数値の下位桁がメモリーの下位にあるような場合に little endian と云う. (元ネタは, ガリバー旅行記の小人国のエピソード.)

例えば, 4バイトの数値 0x04030201 をメモリーに格納した場合以下のようになる. (c.f. endian.h)

Network Byte Order(ネットワークバイトオーダー)とは?

ネットワーク上でのバイトオーダー. ネットワークでデータをやりとりするときのバイト順.

メモリーの内容をネットワークにバイト列として送り出す場合, メモリの先頭バイト(下位アドレス)から順に送りだされる. アーキテクチャが異なるホスト間で数値データを送る場合, どのようなバイト順でデータを扱うか統一しておかないと通信の内容に矛盾がでてしまう. そこで, INET プロトコルのネットワークバイトオーダー(ネットワーク上でのバイトオーダー)として big endian を使うように取り決めている.

ホストバイトオーダーとネットワークバイトオーダーの間で値を変換する手段として, 4バイト値には htonl と ntohl, 2バイト値には htons と ntohs がある.

Big Endian と Little Endian の判別コード

実行時の判定

c.f. C Programming FAQs(by Steve Summit)
int x=1; // 0x00000001
if (*(char*)&x) {
        /* little endian. memory image 01 00 00 00 */
}else{
        /* big endian. memory image 00 00 00 01 */
}

マクロによる判定

GCC-3.1/MacOSX/PowerPC では __BIG_ENDIAN__ がdefine されている.

他の環境でも同様に __*_ENDIAN__ を define するには, c コンパイラに -D__BIG_ENDIAN__ などとパラメータとして与えるか, 適当な *.h ファイルで define すると良い. また, *ENDIAN__ を自動的に define するには, 以下のようにすると良い.

#include <endian.h>

#if !defined(__LITTLE_ENDIAN__) and !defined(__BIG_ENDIAN__) 

#if __BYTE_ORDER == __LITTLE_ENDIAN
#define __LITTLE_ENDIAN__
#elif __BYTE_ORDER == __BIG_ENDIAN
#define __BIG_ENDIAN__
#endif

#endif

関数として判定結果を返す例

事前にマクロが define されていればそれを使い, そうでないなら実行時に判定する.
#include <stdbool.h>

bool sys_is_little_endian(){
#if defined(__LITTLE_ENDIAN__)
        return true;
#elif defined(__BIG_ENDIAN__)
        return false;
#else
        int i = 1;
        return (bool)(*(char*)&i);
#endif
}

Kodama's home / tips.