使用 reinterpret cast 时交换字节序
Swapping endians when using reinterpret cast
当通过网络发送数据时,转换字节数据可以通过以下几种方式实现:
12345 --> {0 0 48 57}
typedef unsigned char byte;
//1. Bit shift
int32_t shiftedInteger = (int32_t) (inBytes[0] << 24 | inBytes[1] << 16 |
inBytes[2] << 8 | inBytes[3]);
//2. Reinterpret cast
int32_t reinterpretedInteger = *reinterpret_cast<int32_t*>(&inBytes);
//3. Using unions
union{
byte b[4];
int32_t i;
}unionCast;
memcpy(unionCast.b,inBytes,4);
int_32t unionCasted = unctionCast.i;
转换数据的最佳方式是什么(在像微处理器这样的 arduino 上使用)?
union 和 reinterpretCast 方法面临大端与小端的问题,但一旦处理浮点数就会派上用场,因为简单的移位不足以将数据转换回来。
使用 reinterpret_cast 时如何交换字节序?
你不能。 Reinterpret_cast 只改变编译器使用的类型,它不接触数据。
如How do I convert between big-endian and little-endian values in C++?中所建议
使用
int32_t __builtin_bswap32 (int32_t x)
您使用 reinterpret 和访问 union 的非活动成员都违反了标准。这样说的规则被称为严格别名。
所以在您的选择中,换档是唯一符合标准的选项。
一个额外的选项——memcpy 直接进入目标类型——也符合标准。
您可以通过 memcpy 合法地对堆栈数组进行适当的放置,按照您的方式放置新的位置,然后 memcpy 返回。优化器将消除 memcpys!
你甚至可以这样做:
template<class T>
struct raw_bytes:
std::array<char, sizeof(T)>
{
static_assert(std::is_pod<T>::value, "pod only");
static raw_bytes to_raw( T in ){
raw_bytes r;
std::memcpy( r.data(), std::addressof(in), sizeof(T) );
return r;
}
// this object no longer valid after convert, but returned reference is until this object destroyed
T& convert(){
char tmp[sizeof(T)];
memcpy(tmp, data(), sizeof(T));
T* r= ::new( (void*)data() ) T;
memcpy(r, tmp, sizeof(T));
return *r;
}
};
可能值得也可能不值得。
您可以将 raw_bytes
粘贴到结构中并将字节块写入其中。然后你可以 convert()
那些字节就地到 T
。返回的引用是合法访问这些字节的唯一途径; raw_bytes
的方法在严格阅读标准下不再合法。
当通过网络发送数据时,转换字节数据可以通过以下几种方式实现:
12345 --> {0 0 48 57}
typedef unsigned char byte;
//1. Bit shift
int32_t shiftedInteger = (int32_t) (inBytes[0] << 24 | inBytes[1] << 16 |
inBytes[2] << 8 | inBytes[3]);
//2. Reinterpret cast
int32_t reinterpretedInteger = *reinterpret_cast<int32_t*>(&inBytes);
//3. Using unions
union{
byte b[4];
int32_t i;
}unionCast;
memcpy(unionCast.b,inBytes,4);
int_32t unionCasted = unctionCast.i;
转换数据的最佳方式是什么(在像微处理器这样的 arduino 上使用)?
union 和 reinterpretCast 方法面临大端与小端的问题,但一旦处理浮点数就会派上用场,因为简单的移位不足以将数据转换回来。 使用 reinterpret_cast 时如何交换字节序?
你不能。 Reinterpret_cast 只改变编译器使用的类型,它不接触数据。
如How do I convert between big-endian and little-endian values in C++?中所建议 使用
int32_t __builtin_bswap32 (int32_t x)
您使用 reinterpret 和访问 union 的非活动成员都违反了标准。这样说的规则被称为严格别名。
所以在您的选择中,换档是唯一符合标准的选项。
一个额外的选项——memcpy 直接进入目标类型——也符合标准。
您可以通过 memcpy 合法地对堆栈数组进行适当的放置,按照您的方式放置新的位置,然后 memcpy 返回。优化器将消除 memcpys!
你甚至可以这样做:
template<class T>
struct raw_bytes:
std::array<char, sizeof(T)>
{
static_assert(std::is_pod<T>::value, "pod only");
static raw_bytes to_raw( T in ){
raw_bytes r;
std::memcpy( r.data(), std::addressof(in), sizeof(T) );
return r;
}
// this object no longer valid after convert, but returned reference is until this object destroyed
T& convert(){
char tmp[sizeof(T)];
memcpy(tmp, data(), sizeof(T));
T* r= ::new( (void*)data() ) T;
memcpy(r, tmp, sizeof(T));
return *r;
}
};
可能值得也可能不值得。
您可以将 raw_bytes
粘贴到结构中并将字节块写入其中。然后你可以 convert()
那些字节就地到 T
。返回的引用是合法访问这些字节的唯一途径; raw_bytes
的方法在严格阅读标准下不再合法。