使用重新解释转换

时间:2018-01-12 12:44:02

标签: 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方法面临大端和小端的问题,但是一旦使用浮点数就会派上用场,因为简单的位移不足以将数据转换回来。 使用reinterpret_cast时如何交换字符串?

2 个答案:

答案 0 :(得分:1)

您使用重新解释和访问非活动成员都违反了标准。这样说的规则被称为严格别名。

所以你的选择,转移是唯一符合标准的选择。

另一个选项 - 直接记入目标类型的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并在其中加入blit字节。然后,您可以将convert()这些字节就地T。返回的引用是合法访问这些字节的唯一方法; raw_bytes的方法在严格阅读标准的情况下不再合法。

答案 1 :(得分:0)

你不能。重新解释强制转换只会更改编译器使用的类型,它不会触及数据。

正如How do I convert between big-endian and little-endian values in C++?中所述 使用

int32_t __builtin_bswap32 (int32_t x)