x86 系の CPU では, 最下位バイトが最初のアドレスに,最上位バイトが最後のアドレスに記憶されます。 「逆順」,LSB First (Least Significant Byte First),Little Endian などと言われています。
逆に多くの RISC CPU (SPARC, ,PPC, 68k など)では, 最上位バイトが最初のアドレスに,最下位バイトが最後のアドレスに記憶されます。 「正順」,MSB First (Most Significant Byte First),Big Endian などと言われています。
数値 正順 逆順 char 12 12 12 int 1234 12 34 34 12 long 12345678 12 34 56 78 78 56 34 12
#include <stdio.h>
#include <stdlib.h>
int main() {
int i = 1;
if(*((char *) &i))
printf("little endian\n");
else if(*((char *) &i + (sizeof(int) - 1)))
printf("big endian\n");
else
printf("unknown\n");
return 0;
}
conv=swabを付ける
conv=conversion[,conversion...]
conversion で指定したファイル変換処理を行う。
swab 奇数バイトと偶数バイトを入れ換える。
Unixのddと異なり、この作業は奇数個のバイトを読み込んだときにもうまく働く。
もし入力が奇数個のバイトを含むなら、最後のバイトは単純にコピーされる(入れ換えるバイトがないからである)。
名前 : swab - 隣接するバイトを交換する
書式 :
#include <string.h> void swab(const void *from, void *to, size_t n);
説明 : swab( ) 関数は、from で指された配列から n バイトを to で指された配列に、隣接した偶数/奇数バイトを交換しながらコピーする。この関数は異なるバイトオーダーを持つマシン間でのデータ交換に使用される。
返り値 : swab( ) 関数は、値を返さない。
名前 : htonl, htons, ntohl, ntohs - ホストバイトオーダーとネットワークバイトオーダーの間で値を変換する
書式 :
#include <netinet/in.h> unsigned long int htonl(unsigned long int hostlong); unsigned short int htons(unsigned short int hostshort); unsigned long int ntohl(unsigned long int netlong); unsigned short int ntohs(unsigned short int netshort);
説明 :
htonl( ) 関数は long integer hostlong をホストバイトオーダーからネットワークバイトオーダーに変換する。
htons( ) 関数は short integer hostshort をホストバイトオーダーからネットワークバイトオーダーに変換する。
ntohl( ) 関数は long integer netlong をネットワークバイトオーダーからホストバイトオーダーに変換する。
ntohs( ) 関数は short integer netshort をネットワークバイトオーダーからホストバイトオーダーに変換する。
i80x86 のホストバイトオーダーでは最下位のバイトが先に配置されるが、 インターネットで用いられるネットワークバイトオーダーでは最上位のバイトが先に配置される。
#ifdef INTEL_CPU
unsigned short swab_w(unsigned short x) {
return ((x << 8) | (x >> 8));
}
unsigned long swab_dw(unsigned long x){
return ((swab_w(x) << 16) | (swab_w(x) >> 16));
}
#else
#define swab_w(x) (x)
#define swab_dw(x) (x)
#endif
以下は Microsoft の資料に載っていたサンプルです。
#define INTEL_CPU
#ifdef INTEL_CPU
/* *************************** FlipLong() ******************************
* Converts a long in "Big Endian" format (ie, Motorola 68000) to Intel
* reverse-byte format, or vice versa if originally in Big Endian.
*********************************************************************
*/
void FlipLong(unsigned char * ptr) {
register unsigned char val;
/* Swap 1st and 4th bytes */
val = *(ptr);
*(ptr) = *(ptr+3);
*(ptr+3) = val;
/* Swap 2nd and 3rd bytes */
ptr += 1;
val = *(ptr);
*(ptr) = *(ptr+1);
*(ptr+1) = val;
}
#endif
/* ************************* FetchLong() *******************************
* Fools the compiler into fetching a long from a char array.
*********************************************************************
*/
unsigned long FetchLong(unsigned long * ptr) {
return(*ptr);
}
/* ************************* ConvertFloat() *****************************
* Converts an 80 bit IEEE Standard 754 floating point number to an unsigned
* long.
********************************************************************** */
unsigned long ConvertFloat(unsigned char * buffer) {
unsigned long mantissa;
unsigned long last = 0;
unsigned char exp;
#ifdef INTEL_CPU
FlipLong((unsigned long *)(buffer+2));
#endif
mantissa = FetchLong((unsigned long *)(buffer+2));
exp = 30 - *(buffer+1);
while (exp--) {
last = mantissa;
mantissa >>= 1;
}
if (last & 0x00000001)
mantissa++;
return(mantissa);
}
/* ************************* StoreLong() ******************************
* Fools the compiler into storing a long into a char array.
********************************************************************
*/
void StoreLong(unsigned long val, unsigned long * ptr) {
*ptr = val;
}
/* ************************** StoreFloat() ******************************
* Converts an unsigned long to 80 bit IEEE Standard 754 floating point
* number.
**********************************************************************
*/
void StoreFloat(unsigned char * buffer, unsigned long value) {
unsigned long exp;
unsigned char i;
memset(buffer, 0, 10);
exp = value;
exp >>= 1;
for (i=0; i<32; i++) {
exp>>= 1;
if (!exp)
break;
}
*(buffer+1) = i;
for (i=32; i; i--) {
if (value & 0x80000000)
break;
value <<= 1;
}
StoreLong(value, buffer+2);
#ifdef INTEL_CPU
FlipLong((unsigned long *)(buffer+2));
#endif
}