如何在c++中转换大端值和小端值?
为了清晰起见,我必须将二进制数据(双精度浮点值以及32位和64位整数)从一个CPU架构转换到另一个CPU架构。这并不涉及网络,因此ntoh()和类似的函数在这里不能工作。
注意:我接受的答案直接适用于我的目标编译器(这就是我选择它的原因)。然而,这里还有其他非常好的、更方便的答案。
如何在c++中转换大端值和小端值?
为了清晰起见,我必须将二进制数据(双精度浮点值以及32位和64位整数)从一个CPU架构转换到另一个CPU架构。这并不涉及网络,因此ntoh()和类似的函数在这里不能工作。
注意:我接受的答案直接适用于我的目标编译器(这就是我选择它的原因)。然而,这里还有其他非常好的、更方便的答案。
当前回答
和在C中一样:
short big = 0xdead;
short little = (((big & 0xff)<<8) | ((big & 0xff00)>>8));
您还可以声明一个无符号字符的向量,将输入值memcpy放入其中,将字节反向转换为另一个向量,然后将字节memcpy取出,但这将花费比旋转位长几个数量级的时间,特别是对于64位值。
其他回答
如果您这样做是为了在不同平台之间传输数据,请查看ntoh和hton函数。
我们已经用模板做到了这一点。你可以这样做:
// Specialization for 2-byte types.
template<>
inline void endian_byte_swapper< 2 >(char* dest, char const* src)
{
// Use bit manipulations instead of accessing individual bytes from memory, much faster.
ushort* p_dest = reinterpret_cast< ushort* >(dest);
ushort const* const p_src = reinterpret_cast< ushort const* >(src);
*p_dest = (*p_src >> 8) | (*p_src << 8);
}
// Specialization for 4-byte types.
template<>
inline void endian_byte_swapper< 4 >(char* dest, char const* src)
{
// Use bit manipulations instead of accessing individual bytes from memory, much faster.
uint* p_dest = reinterpret_cast< uint* >(dest);
uint const* const p_src = reinterpret_cast< uint const* >(src);
*p_dest = (*p_src >> 24) | ((*p_src & 0x00ff0000) >> 8) | ((*p_src & 0x0000ff00) << 8) | (*p_src << 24);
}
似乎安全的方法是在每个单词上使用“顿音”。所以,如果你有。
std::vector<uint16_t> storage(n); // where n is the number to be converted
// the following would do the trick
std::transform(word_storage.cbegin(), word_storage.cend()
, word_storage.begin(), [](const uint16_t input)->uint16_t {
return htons(input); });
如果您是在一个大端系统上,那么上面的代码将是一个无操作,因此我将查找您的平台使用的任何编译时条件,以确定htons是否是一个无操作。毕竟是O(n)在Mac上,它会是这样的……
#if (__DARWIN_BYTE_ORDER != __DARWIN_BIG_ENDIAN)
std::transform(word_storage.cbegin(), word_storage.cend()
, word_storage.begin(), [](const uint16_t input)->uint16_t {
return htons(input); });
#endif
我喜欢这个,只是为了风格:-)
long swap(long i) {
char *c = (char *) &i;
return * (long *) (char[]) {c[3], c[2], c[1], c[0] };
}
void writeLittleEndianToBigEndian(void* ptrLittleEndian, void* ptrBigEndian , size_t bufLen )
{
char *pchLittleEndian = (char*)ptrLittleEndian;
char *pchBigEndian = (char*)ptrBigEndian;
for ( size_t i = 0 ; i < bufLen ; i++ )
pchBigEndian[bufLen-1-i] = pchLittleEndian[i];
}
std::uint32_t row = 0x12345678;
char buf[4];
writeLittleEndianToBigEndian( &row, &buf, sizeof(row) );