簡體   English   中英

在C ++中將字節數組轉換為int

[英]Byte array to int in C++

以下是從字節數組中獲取int16(短)值的最有效方法嗎?

inline __int16* ReadINT16(unsigned char* ByteArray,__int32 Offset){
    return (__int16*)&ByteArray[Offset];
};

如果字節數組包含與機器相同的endian格式的字節轉儲,則調用此代碼。 歡迎替代方案。

這取決於“高效”的含義,但請注意,在某些體系結構中,如果Offset為奇數,則此方法將失敗,因為生成的16位int將未對齊,並且當您隨后嘗試訪問它時將獲得異常。 如果可以保證Offset是偶數,則應該只使用此方法,例如

inline int16_t ReadINT16(uint8_t *ByteArray, int32_t Offset){
    assert((Offset & 1) == 0); // Offset must be multiple of 2
    return *(int16_t*)&ByteArray[Offset];
};

還要注意,我稍微改變了這一點,以便它直接返回一個16位值,因為返回一個指針然后隨后取消引用它很可能不會直接返回16位值。 我也為整數切換到標准Posix類型 - 我建議你也這樣做。

我很驚訝沒有人建議這個解決方案在所有架構中都是安全正確的 (好吧,任何有8位到一個字節的架構)。

inline int16_t ReadINT16(uint8_t *ByteArray, int32_t Offset)
{
    int16_t result;
    memcpy(&result, ByteArray+Offset, sizeof(int16_t));
    return result;
};

我想可以避免memcpy的開銷:

inline int16_t ReadINT16(uint8_t *ByteArray, int32_t Offset)
{
    int16_t result;
    uint8_t* ptr1=(uint8_t*)&result;
    uint8_t* ptr2 = ptr1+1;
    *ptr1 = *ByteArray;
    *ptr2 = *(ByteArray+1);
    return result;
};

我認為對齊問題不會在x86上生成異常。 如果我記得,Windows(當它在Dec Alpha和其他人上運行時)將捕獲對齊異常並將其修復(在適度的性能命中)。 而且我確實記得當你遇到對齊問題時,學習Sparc on SunOS的困難方法就會讓崩潰失敗。

我覺得這沒問題,這正是我要做的。 只要字節數組可以安全訪問,並確保偏移是正確的(短路是2個字節,所以你可能想要確保它們不能做奇數偏移或類似的東西)

inline __int16* ReadINT16(unsigned char* ByteArray,__int32 Offset)
{     
    return (__int16*)&ByteArray[Offset]; 
}; 

不幸的是,這在C ++中有未定義的行為,因為您使用兩種不同的類型訪問存儲,這在嚴格的別名規則下是不允許的。 您可以使用char*訪問類型的存儲,但不能相反。

從我之前提出的問題來看,唯一安全的方法是使用memcpy將字節復制到int然后使用它。 (這可能會針對您希望的相同代碼進行優化,因此看起來非常低效)。

你的代碼可能會工作,而且大多數人似乎都這樣做......但重點是,有一天你不能向你的編譯器供應商哭泣,因為有一天它會生成你不希望做的代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM