以下是从字节数组中获取int16(短)值的最有效方法吗?
inline __int16* ReadINT16(unsigned char* ByteArray,__int32 Offset){
return (__int16*)&ByteArray[Offset];
};
如果字节数组包含与机器相同的endian格式的字节转储,则调用此代码。欢迎替代方案。
答案 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然后使用它。 (这可能会针对您希望的相同代码进行优化,因此只需看起来非常低效)。
您的代码可能会起作用,而且大多数人似乎都这样做......但重点是,当有一天它生成不符合您希望的代码时,您无法向编译器供应商哭泣