c++ - neutral - windows endianness




從char*數組中讀取“整數”大小的字節。 (6)

我想從char*數組中讀取sizeof(int)字節。

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

b)您如何閱讀前四個字節,或者考慮是否考慮字節序。

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

什麼是最好的方法去解決這個問題


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

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

在這兩種情況下,你都需要對大於1個字節的所有數字進行字節交換,例如shorts,ints,longs,double等。但是,如果你總是處理來自同一平台的數據,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));
}

你的意思是這樣嗎?:

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

如果數據的來源來自不同的平台,比如設備,那麼您只需要擔心字節數。


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


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


為什麼要閱讀,當你可以比較?

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

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


解決這個問題的簡單方法是確保生成的字節以一致的字節順序排列。 通常,各種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




endianness