c++ - 使用 reinterpret cast 时交换字节序

标签 c++ endianness 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 方法面临大端与小端的问题,但一旦处理 float 就会派上用场,因为简单的移位不足以将数据转换回来。 使用 reinterpret_cast 时如何交换字节序?

最佳答案

您对 reinterpret 的使用和访问 union 的非事件成员都违反了标准。如此规定的规则称为严格别名。

因此,在您的选择中,移动是唯一符合标准的选项。

一个额外的选项——memcpy 直接进入目标类型——也符合标准。

您可以通过 memcpy 合法地将堆栈数组放置在合适的位置,放置新的 bew tyoe,然后 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 粘贴到结构中并将字节 block 写入其中。然后您可以将这些字节convert() 就地转换为T。返回的引用是合法访问这些字节的唯一途径; raw_bytes 的方法在严格阅读标准下不再合法。

关于c++ - 使用 reinterpret cast 时交换字节序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48226557/

相关文章:

python - sin_family 的网络字节顺序

c++ - 严格别名和 std::array 与 C 风格数组

c++ - 标准布局类型和 reinterpret_cast

c++ - c++修改basic_ostream对象的内容,或者,删除basic_ostream对象的数据内容

c++ - UB 具有不同类型的结构铸件?

c++ - C++中new的使用

c++ - 移动 strchr 指针后使用 strtok

python - python struct.pack 中的位顺序

c++ - 将 uint16_t 解释为 int16_t

c++ - 正确的固定大小数组的 c++ 样式转换?