2009-02-13 78 views
12

我想從char*數組中讀取sizeof(int)個字節。從char *數組中讀取「整數」大小的字節。

a)在什麼情況下我們需要擔心是否需要檢查字節序?

b)如何讀取前4個字節,或者考慮是否考慮字節順序。

編輯:我已閱讀的sizeof(int)字節需要與整數值進行比較。

什麼是去了解這個問題的最好辦法

+0

我對你想要做的事情有點困惑。你能寫一些僞代碼作爲例子嗎?你想從字符數組解析整數嗎? – 2009-02-13 06:43:52

+0

我想從char *數組中找到sizeof(int)字節,並試圖將它與一個整數進行比較。數據的來源是不同的機器。 – kal 2009-02-13 06:57:19

回答

1

你不應該需要擔心endianess的,除非你正在閱讀從不同的機器,例如上創建的源字節一個網絡流。

鑑於這一點,你不能只使用for循環?

void ReadBytes(char * stream) { 
    for (int i = 0; i < sizeof(int); i++) { 
     char foo = stream[i]; 
     } 
    } 
} 

你在問什麼比這更復雜的東西?

+0

我的數據實際上是從其他來源創建的 – kal 2009-02-13 06:55:37

1

只有當您正在閱讀的數據由大於一個字節的數字組成時,您才需要擔心字節數。
如果您正在閱讀sizeof(int)字節並希望將它們解釋爲int,那麼endianess會有所作爲。基本上endianness是機器將一系列多於1個字節解釋爲數值的方式。

3

取決於你想如何閱讀,我得到了你想要投4個字節轉換成整數,這樣通過網絡流數據通常會在這樣的事情結束了的感覺:

int foo = *(int*)(stream+offset_in_stream); 
+1

這可能會導致未對齊的訪問。 – gimpf 2009-02-13 06:56:53

+0

@gimpf:我很好奇:在哪些系統上會導致錯誤? – Christoph 2009-02-13 11:15:45

+0

I.e.在80486和任何更好的CPU與對齊標誌設置。 – 2009-02-13 15:48:29

18

待辦事項你的意思是這樣的?:

char* a; 
int i; 
memcpy(&i, a, sizeof(i)); 

你只需要擔心如果字節序的數據的來源是不同的平臺,就像一個設備。

1

只需使用for循環在sizeof(int)塊中移動數組。
使用函數ntohl(至少在Linux上的標頭<arpa/inet.h>中找到)將網絡順序中的字節(網絡順序定義爲big-endian)轉換爲本地字節順序。該庫函數的實現可以爲您運行的任何處理器執行正確的網絡到主機轉換。

9

a)如果數據是在big-endian機器上創建的,並且正在小端機器上處理,或者反過來,則只需要擔心「字節順序」(即字節交換)。有很多方法可以發生,但這裏有幾個例子。

  1. 您通過套接字在Windows機器上接收數據。 Windows採用小端架構,而網絡數據「應該」採用大端格式。
  2. 您處理在具有不同「字節順序」的系統上創建的數據文件。

無論在哪種情況下,都需要對所有大於1個字節的數字進行字節交換,例如,,短褲,整數,長褲,雙打等等。但是,如果你總是在處理來自同一個平臺的數據,那麼endian問題就不成問題。

b)根據你的問題,這聽起來像你有一個字符指針,並希望提取前4個字節爲int,然後處理任何endian問題。要進行提取,請使用:

int n = *(reinterpret_cast<int *>(myArray)); // where myArray is your data 

顯然,這裏假定myArray不是空指針;否則,由於它將指針取消引用,所以會崩潰,因此請使用良好的防禦性編程方案。

要交換Windows上的字節,可以使用winsock2.h中定義的ntohs()/ ntohl()和/或htons()/ htonl()函數。或者你也可以寫一些簡單的程序來做到這一點在C++中,例如:

inline unsigned short swap_16bit(unsigned short us) 
{ 
    return (unsigned short)(((us & 0xFF00) >> 8) | 
          ((us & 0x00FF) << 8)); 
} 

inline unsigned long swap_32bit(unsigned long ul) 
{ 
    return (unsigned long)(((ul & 0xFF000000) >> 24) | 
          ((ul & 0x00FF0000) >> 8) | 
          ((ul & 0x0000FF00) << 8) | 
          ((ul & 0x000000FF) << 24)); 
} 
3

最簡單的辦法來解決,這是確保任何生成字節一致的字節序這樣做。通常,各種TCP/IP內容所使用的「網絡字節順序」最好是:庫函數htonlntohl對此非常有效,它們的 通常相當優化。

但是,如果網絡字節順序未被使用,您可能需要以其他方式執行 。你需要知道兩件事:一個整數的大小和字節順序。 一旦你知道這一點,你就知道要提取多少個字節,並按照何種順序將它們放在一起。

,它假定的sizeof(int)的一些示例代碼是字節的正確數量:

#include <limits.h> 

int bytes_to_int_big_endian(const char *bytes) 
{ 
    int i; 
    int result; 

    result = 0; 
    for (i = 0; i < sizeof(int); ++i) 
     result = (result << CHAR_BIT) + bytes[i]; 
    return result; 
} 

int bytes_to_int_little_endian(const char *bytes) 
{ 
    int i; 
    int result; 

    result = 0; 
    for (i = 0; i < sizeof(int); ++i) 
     result += bytes[i] << (i * CHAR_BIT); 
    return result; 
} 


#ifdef TEST 

#include <stdio.h> 

int main(void) 
{ 
    const int correct = 0x01020304; 
    const char little[] = "\x04\x03\x02\x01"; 
    const char big[] = "\x01\x02\x03\x04"; 

    printf("correct: %0x\n", correct); 
    printf("from big-endian: %0x\n", bytes_to_int_big_endian(big)); 
    printf("from-little-endian: %0x\n", bytes_to_int_little_endian(little)); 
    return 0; 
} 

#endif 
1

爲什麼閱讀時,你可以比較?

bool AreEqual(int i, char *data) 
{ 
    return memcmp(&i, data, sizeof(int)) == 0; 
} 

如果您在需要將所有整數轉換爲某種不變形式時擔心排序。 htonl和ntohl就是很好的例子。

3

如何

int int_from_bytes(const char * bytes, _Bool reverse) 
{ 
    if(!reverse) 
     return *(int *)(void *)bytes; 

    char tmp[sizeof(int)]; 

    for(size_t i = sizeof(tmp); i--; ++bytes) 
     tmp[i] = *bytes; 

    return *(int *)(void *)tmp; 
} 

你會使用這樣的:

int i = int_from_bytes(bytes, SYSTEM_ENDIANNESS != ARRAY_ENDIANNESS); 

如果你是哪裏的鑄造void *int *可能導致對準衝突的系統上,你可以使用

int int_from_bytes(const char * bytes, _Bool reverse) 
{ 
    int tmp; 

    if(reverse) 
    { 
     for(size_t i = sizeof(tmp); i--; ++bytes) 
      ((char *)&tmp)[i] = *bytes; 
    } 
    else memcpy(&tmp, bytes, sizeof(tmp)); 

    return tmp; 
}