2012-12-03 131 views
11

轉換的字節數組時到短/ INT /長我想知道如果系統字節序的事項。如果代碼在big-endian和little-endian機器上運行,這會不正確嗎?轉換字節陣列(char數組),以一個整數類型(短整型,整型,長)

short s = (b[0] << 8) | (b[1]); 
int i = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3]) 
+0

如果你在同一臺機器上做那麼沒有也沒關係,如果您要發送它在網絡上的機器*威力*有不同的字節序,然後試圖轉換,那麼是的,這很重要。 –

+2

簡短的回答是,大於1個字節的整數對字節順序很重要。不適用於其他任何東西(在「普通」計算機上) – xaxxon

回答

12

是的,字節順序很重要。在little endian中,short或int的上半部分是最重要的字節 - 即short爲8-15,int爲24-31。大端字節順序將需要扭轉:

short s = ((b[1] << 8) | b[0]); 
int i = (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | (b[0]); 

注意,這個假設的字節數組是小尾數順序。字節數組和整數類型之間的字節順序和轉換不僅取決於CPU的字節順序,還取決於字節數組數據的字節順序。

建議在功能將知道(或者通過編譯標誌或在運行時)來包裝這些轉換的系統的字節序和正確地執行轉換。

另外,開創了字節數組數據的標準(總是大端,例如),然後使用socketntoh_sntoh_l會卸載有關字節序的OS socket實現,意識到這樣的事情的決定。請注意,默認的網絡順序是big endian(n,位於ntoh_x),所以將字節數組數據設置爲big endian是實現此目的最直接的方法。

作爲由OP(@Mike),boost還提供端序轉換函數指出。

+0

如何在同一機器上使用與CPU不同的字節序列數據? –

+0

嗯好吧,讓所有的字節數組在big-endian中確實讓事情變得更簡單。因此,爲了轉換爲實際類型,我可以使用類似boost的asio庫來完成上述代碼之後的轉換(例如s = ntohs(s)),並且在編碼時,我可以使用htons() – Mike

+0

@HunterMcMillen - Easy:for短0x1234你可以有字節數組[0x12,0x34]和[0x34,0x12]。第一個是大端,第二個是小端。 –

0

沒有,那也沒關係,只要字節順序而言的,但你可能有問題,如果你的int s爲只有16位寬。

0

你指定的問題,你正在使用現有的字節數組,將在所有機器上正常工作。你會得到相同的答案。

但是,這取決於你如何創建一個流,可以通過字節序的影響,可能會無法用你認爲你會數結束。

1
// on little endian: 

unsigned char c[] = { 1, 0 };  // "one" in little endian order { LSB, MSB } 

int a = (c[1] << 8) | c[0];   // a = 1 

// ----------------------------------------- -----------------------------------

// on big endian: 

unsigned char c[] = { 0, 1 };  // "one" in big endian order { MSB, LSB } 

int a = (c[1] << 8) | c[0];   // a = 1 

// ------ -------------------------------------------------- --------------------

// on little endian: 

unsigned char c[] = { 0, 1 };  // "one" in big endian order { MSB, LSB } 

int a = (c[0] << 8) | c[1];   // a = 1 (reverse byte order) 

// --------------------- -------------------------------------------------- -----

// on big endian: 

unsigned char c[] = { 1, 0 };  // "one" in little endian order { LSB, MSB } 

int a = (c[0] << 8) | c[1];   // a = 1 (reverse byte order) 
0

您可以爲此使用工會。字節順序很重要,爲了改變它,你可以使用x86 BSWAP指令(或其他平臺的類似物),由大多數c編譯器提供作爲內部函數。

#include <stdio.h> 
typedef union{ 
    unsigned char bytes[8]; 
    unsigned short int words[4]; 
    unsigned int dwords[2]; 
    unsigned long long int qword; 
} test; 
int main(){ 
    printf("%d %d %d %d %d\n", sizeof(char), sizeof(short), sizeof(int), sizeof(long), sizeof(long long)); 
    test t; 
    t.qword=0x0001020304050607u; 
    printf("%02hhX|%02hhX|%02hhX|%02hhX|%02hhX|%02hhX|%02hhX|%02hhX\n",t.bytes[0],t.bytes[1] ,t.bytes[2],t.bytes[3],t.bytes[4],t.bytes[5],t.bytes[6],t.bytes[7]); 
    printf("%04hX|%04hX|%04hX|%04hX\n" ,t.words[0] ,t.words[1] ,t.words[2] ,t.words[3]); 
    printf("%08lX|%08lX\n" ,t.dwords[0] ,t.dwords[1]); 
    printf("%016qX\n" ,t.qword); 
    return 0; 
}