2017-01-23 71 views
1

我经常遇到这样的情况,即通过协议接收打包的二进制数据(即变量未正确对齐的地方),数据通常以std :: string,std :: vector或其他方式出现这样的容器。什么是从二进制缓冲区初始化变量的正确方法?

我的问题是解压这些数据的最佳做法是什么?我通常将执行类似:

int32_t x = *((int32_t*)charPtr); 

或迭代器

int32_t x = *((int32_t*)(&(*itt))); 

但这些真的感觉像一个黑客,虽然他们可以在一个模板函数包裹起来,是不是有一个更直接告诉编译器我想要什么?

+0

如果有之间的字节序不一致发件人/协议和您的代码进行接收处理,除了您要求的以外,还有其他一些考虑因素。除了显而易见的,例如一些协议在WORD级别定义了Endian - ness,但是在DWORD级别没有,所以你可能有这个处理。 – franji1

+0

我很确定,如果你使用intX_t并且你正在使用本地机器(即没有endian不匹配风险),那么这两个表达式都可以工作,并且不会产生未定义的行为,显然在使用之前,你应该确保你有在初始之后至少有X - 1个字符。如果您已经有char指针,则使用第一个字符指针,或者使用第二个字符指针或: &myvector [x]或&mystring [x]作为charPtr。 – gabry

回答

1

正确,避免不确定的行为,这样做的方法是:

int32_t x; 
memcpy(&x, charPtr, sizeof(x)); 

,你可以在一个函数模板包:

template <class T, 
    std::enable_if_t<std::is_trivially_default_constructible<T>::value && 
     std::is_trivially_copyable<T>::value, int> = 0> 
T unpack(unsigned char* p) { 
    T val; 
    memcpy(&val, p, sizeof(val)); 
    return val; 
} 
+0

如果他在本地计算机上工作,则会定义该行为,您的代码将添加不需要的副本开销...... – gabry

+0

@gabry只有在存在'charPtr'处存在类型为'int32_t'的对象时才定义。 – Barry

+0

@gabry另外OP想要一个副本... – Barry

相关问题