在C ++中将字节数组转换为int

时间:2011-07-28 06:56:02

标签: c++

以下是从字节数组中获取int16(短)值的最有效方法吗?

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

如果字节数组包含与机器相同的endian格式的字节转储,则调用此代码。欢迎替代方案。

4 个答案:

答案 0 :(得分:7)

这取决于“高效”的含义,但请注意,在某些体系结构中,如果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类型 - 我建议你也这样做。

答案 1 :(得分:4)

我很惊讶没有人建议使用所有架构中的对齐安全正确的解决方案。 (好吧,任何一个字节有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对SunOS的严厉解决方法。

答案 2 :(得分:0)

我认为没有问题,这正是我要做的。只要字节数组可以安全访问,并确保偏移是正确的(短路是2个字节,所以你可能想要确保它们不能做奇数偏移或类似的东西)

答案 3 :(得分:0)

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

不幸的是,这在C ++中有未定义的行为,因为您使用两种不同的类型访问存储,这在严格的别名规则下是不允许的。您可以使用char*访问类型的存储,但不能相反。

从我之前提出的问题来看,唯一安全的方法是使用memcpy将字节复制到int然后使用它。 (这可能会针对您希望的相同代码进行优化,因此只需看起来非常低效)。

您的代码可能会起作用,而且大多数人似乎都这样做......但重点是,当有一天它生成不符合您希望的代码时,您无法向编译器供应商哭泣