?????? little endian和big endian是表示計(jì)算機(jī)字節(jié)順序的兩種格式,所謂的字節(jié)順序指的是長度跨越多個(gè)字節(jié)的數(shù)據(jù)的存放形式.
??????? 假設(shè)從地址0x00000000開始的一個(gè)字中保存有數(shù)據(jù)0x1234abcd,那么在兩種不同的內(nèi)存順序的機(jī)器上從字節(jié)的角度去看的話分別表示為:
?????? 1)little endian:在內(nèi)存中的順序是0x00000000-0xcd,0x00000001-0xab,0x00000002-0x34,0x00000003-0x12
?????? 2)big? endian:在內(nèi)存中的順序是0x00000000-0x12,0x00000001-0x34,0x00000002-0xab,0x00000003-0xcd
?????? 需要特別說明的是,以上假設(shè)機(jī)器是每個(gè)內(nèi)存單元以8位即一個(gè)字節(jié)為單位的.
?????? 簡單的說,little endian把低位存放到高位,而big endian把低位存放到低位.
?????? 現(xiàn)在主流的CPU,intel系列的是采用的little endian的格式存放數(shù)據(jù),而motorola系列的CPU采用的是big endian.
??????
?????? 以下是判斷字節(jié)存儲(chǔ)順序的可移植的C語言代碼:
??????
/**/
/*
*******************************************************************
????created:????2006-9-5
????filename:?????test.cpp
????author:????????李創(chuàng)
????
????purpose:????可移植的用于判斷存儲(chǔ)格式是
????????????????little?endian還是big?ednian的C代碼
????????????????取自<<C:?A?Reference?Manual>>
********************************************************************
*/
#include?
<
stdio.h
>
union

{
????
long
?Long;
????
char
?Char[
sizeof
(
long
)];
}
u;

int
?main()

{????
????u.Long?
=
?
1
;
????
????
if
?(u.Char[
0
]?
==
?
1
)????

????
{
????????printf(
"
Little?Endian!\n
"
);
????}
????
else
?
if
?(u.Char[
sizeof
(
long
)?
-
?
1
]?
==
?
1
)

????
{
????????printf(
"
Big?Endian!\n
"
);
????}
????
else
????
{
????????printf(
"
Unknown?Addressing!\n
"
);
????}
????printf(
"
Now,?Let's?look?at?every?byte?in?the?memory!\n
"
);
????
for
?(
int
?i?
=
?
0
;?i?
<
?
sizeof
(
long
);?
++
i)

????
{
????????printf(
"
[%x]?=?%x\n
"
,?
&
u.Char[i],?u.Char[i]);
????}
????
return
?
0
;
}
?
?????? 很多人認(rèn)為掌握這個(gè)知識(shí)是不必要,其實(shí)不然.在網(wǎng)絡(luò)編程中,TCP/IP統(tǒng)一采用big endian方式傳送數(shù)據(jù),也就是說,假設(shè)現(xiàn)在是在一個(gè)字節(jié)順序是little endian的機(jī)器上傳送數(shù)據(jù),要求傳送的數(shù)據(jù)是0XCEFABOBO,那么你就要以0XBOBOFACE的順序在unsigned int中存放這個(gè)數(shù)據(jù),只有這樣才能保證存放的順序滿足TCP/IP的字節(jié)順序要求.很多時(shí)候,需要自己編寫應(yīng)用層的協(xié)議,字節(jié)順序的概念在這個(gè)時(shí)候就顯得及其的重要了.
?????? 下面給出的是在big endian和little endian中相互轉(zhuǎn)換的代碼,C語言強(qiáng)大的位操作的能力在這里顯示了出來:
????????
/**/
/*
*******************************************************************
????created:????2006-9-5
????filename:?????get32put32.cpp
????author:????????李創(chuàng)
????
????purpose:????在little?endian和big?ednian之間相互轉(zhuǎn)化數(shù)據(jù)的演示代碼

********************************************************************
*/
#include?
<
stdio.h
>
const
?unsigned?
char
?SIZE_OF_UNSIGNEDINT??
=
?
sizeof
(unsigned?
int
);
const
?unsigned?
char
?SIZE_OF_UNSIGNEDCHAR?
=
?
sizeof
(unsigned?
char
);

void
?put_32(unsigned?
char
?
*
cmd,?unsigned?
int
?data)

{
????
int
?i;
????
for
?(i?
=
?SIZE_OF_UNSIGNEDINT?
-
?
1
;?i?
>=
?
0
;?
--
i)

????
{
????????cmd[i]?
=
?data?
%
?
256
;
????????
//
?或者可以:
????????
//
cmd[i]?=?data?&?0xFF;
????????data?
=
?data?
>>
?
8
;
????}
}
unsigned?
int
?get_32(unsigned?
char
?
*
cmd)

{
????unsigned?
int
??ret;
????
int
?i;

????
for
?(ret?
=
?
0
,?i?
=
?SIZE_OF_UNSIGNEDINT?
-
?
1
;?i?
>=
?
0
;?
--
i)

????
{
????????ret??
=
?ret?
<<
?
8
;
????????ret?
|=
?cmd[i];????????
????}
????
????
return
?ret;
}
int
?main(
void
)

{
????unsigned?
char
?cmd[SIZE_OF_UNSIGNEDINT];
????unsigned?
int
?data,?ret;
????unsigned?
char
?
*
p;
????
int
?i;

????data?
=
?
0x12345678
;
????printf(
"
data?=?%x\n
"
,?data);
????
//
?以字節(jié)為單位打印出數(shù)據(jù)
????p?
=
?(unsigned?
char
*
)(
&
data);
????
for
?(i?
=
?
0
;?i?
<
?SIZE_OF_UNSIGNEDINT;?
++
i)

????
{
????????printf(
"
%x
"
,?
*
p
++
);
????}
????printf(
"
\n
"
);

????
//
?以相反的順序存放到cmd之中
????put_32(cmd,?data);
????
for
?(i?
=
?
0
;?i?
<
?SIZE_OF_UNSIGNEDINT;?
++
i)

????
{
????????printf(
"
cmd[%d]?=?%x\n
"
,?i,?cmd[i]);
????}
????
//
?再以相反的順序保存數(shù)據(jù)到ret中
????
//
?保存之后的ret數(shù)值應(yīng)該與data相同
????ret?
=
?get_32(cmd);
????printf(
"
ret?=?%x\n
"
,?ret);
????p?
=
?(unsigned?
char
*
)(
&
ret);
????
for
?(i?
=
?
0
;?i?
<
?SIZE_OF_UNSIGNEDINT;?
++
i)

????
{
????????printf(
"
%x
"
,?
*
p
++
);
????}
????printf(
"
\n
"
);

????
return
?
0
;
}
參考資料:<<C: A Reference Manual>>