在計(jì)算機(jī)科學(xué)領(lǐng)域中,字節(jié)序是指存放多字節(jié)數(shù)據(jù)的字節(jié)(byte)的順序,典型的情況是整數(shù)在內(nèi)存中的存放方式和網(wǎng)絡(luò)傳輸?shù)膫鬏旐樞?。不同的處理器所采用的字?jié)序可能是不同的,例如: x86,6502, Z80, VAX,和 PDP-11都是采用小端字節(jié)序,而 Motorola 6800 、 68k, IBM POWER, 和 System/360則采用大端字節(jié)序。另外,網(wǎng)絡(luò)協(xié)議通常也會規(guī)定其所采用的字節(jié)序,還有像java這樣的語言,也是規(guī)定了字節(jié)序的(tcp/ip和java都是采用大端字節(jié)序)。
通常,系統(tǒng)中會提供ntohs、htons、ntohl、htonl這4個(gè)函數(shù),已實(shí)現(xiàn)16位和32位本地字節(jié)序和網(wǎng)絡(luò)字節(jié)序的轉(zhuǎn)換。但是,目前好像還沒有提供64位數(shù)據(jù)字節(jié)序的轉(zhuǎn)換函數(shù)。所以,在這里自己動手寫一個(gè)。
首先,我們要判斷本地系統(tǒng)所采用的字節(jié)序:
- #define BigEndian 1
- #define LittleEndian 0
- static bool BigEndianTest()
- {
- /*定義一個(gè)2個(gè)字節(jié)長度的數(shù)據(jù),并賦值為1,則n的16進(jìn)制表示為0x0001
- 如果系統(tǒng)以“大端”存放數(shù)據(jù),也即是以MSB方式存放,那么低字節(jié)存放的必定是0x00,高字節(jié)存放的必定是0x01
- 如果系統(tǒng)以“小端”存放數(shù)據(jù),也即是以LSB方式存放,那么低字節(jié)存放的必定是0x01,高字節(jié)存放的必定是0x00
- 所謂MSB,就是將最重要的位存入低位,而LSB則是將最不重要的位存入低位
- 我們可以通過檢測低位的數(shù)值就可以知道系統(tǒng)的字節(jié)序
- */
- const __int16 n = 1;
- if(*(char *)&n)
- {
- return LittleEndian;
- }
- return BigEndian;
- }
當(dāng)然這里可以再優(yōu)化一下,寫成宏定義。
然后,定義16、32、64位的調(diào)位函數(shù)。這里就是字節(jié)“搬家”而已。
- #define Swap16(s) ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff))
- #define Swap32(l) (((l) >> 24) | /
- (((l) & 0x00ff0000) >> 8) | /
- (((l) & 0x0000ff00) << 8) | /
- ((l) << 24))
- #define Swap64(ll) (((ll) >> 56) |/
- (((ll) & 0x00ff000000000000) >> 40) |/
- (((ll) & 0x0000ff0000000000) >> 24) |/
- (((ll) & 0x000000ff00000000) >> 8) |/
- (((ll) & 0x00000000ff000000) << 8) |/
- (((ll) & 0x0000000000ff0000) << 24) |/
- (((ll) & 0x000000000000ff00) << 40) |/
- (((ll) << 56)))
最后,
- #define BigEndian_16(s) BigEndianTest() ? s : Swap16(s)
- #define LittleEndian_16(s) BigEndianTest() ? Swap16(s) : s
- #define BigEndian_32(l) BigEndianTest() ? l : Swap32(l)
- #define LittleEndian_32(l) BigEndianTest() ? Swap32(l) : l
- #define BigEndian_64(ll) BigEndianTest() ? ll : Swap64(ll)
- #define LittleEndian_64(ll) BigEndianTest() ? Swap64(ll) : ll
現(xiàn)在,我們來測試一下:
- int main()
- {
- unsigned __int16 i16 = 0xabcd;
- unsigned __int32 i32 = 0x0a0b0c0d;
- unsigned __int64 i64 = 0x0102030405060708;
- printf("System is %s/n",BigEndianTest() ? "BigEndian" : "LittleEndian" );
- printf("__int16 i16 = 0x%x, BigEndian:0x%x htons:0x%x, LittleEndian:0x%x ntohs:0x%x/n",
- i16,BigEndian_16(i16),htons(i16),LittleEndian_16(i16),ntohs(BigEndian_16(i16)));
- printf("__int32 i32 = 0x%x, BigEndian:0x%x htons:0x%x, LittleEndian:0x%x ntohs:0x%x/n",
- i32,BigEndian_32(i32),htonl(i32),LittleEndian_32(i32),ntohl(BigEndian_32(i32)));
- printf("__int64 i64 = 0x%llx, BigEndian:0x%llx, LittleEndian:0x%llx/n",i64,
- BigEndian_64(i64),LittleEndian_64(i64));
- getchar();
- return 0;
- }
運(yùn)行結(jié)果如下:
- System is LittleEndian
- __int16 i16 = 0xabcd, BigEndian:0xcdab htons:0xcdab, LittleEndian:0xabcd ntohs:0
- xabcd
- __int32 i32 = 0xa0b0c0d, BigEndian:0xd0c0b0a htons:0xd0c0b0a, LittleEndian:0xa0b
- 0c0d ntohs:0xa0b0c0d
- __int64 i64 = 0x102030405060708, BigEndian:0x807060504030201, LittleEndian:0x102
- 030405060708
|