[英]How to convert a byte array of size 64 to a list of double values in Arduino C++?
void Manager::byteArrayToDoubleArray(byte ch[]) {
int counter = 0;
// temp array to break the byte array into size of 8 and read it
byte temp[64];
// double result values
double res[8];
int index = 0;
int size = (sizeof(ch) / sizeof(*ch));
for (int i = 0; i < size; i++) {
counter++;
temp[i] = ch[i];
if (counter % 8 == 0) {
res[index] = *reinterpret_cast<double * const>(temp);
index++;
counter = 0;
}
}
}
在这里, result
将是count = 8
的双精度值列表。
您的问题是两件事。 您有一些错别字和误解。 C ++标准在此方面有些破损。
我会尝试同时修复。
首先,一个帮助函数,叫做laundry_pods
。 它需要原始内存,然后将其“清洗”到您选择的类型的数组中,只要您选择容器类型:
template<class T, std::size_t N>
T* laundry_pods( void* ptr ) {
static_assert( std::is_pod<std::remove_cv_t<T>>{} );
char optimized_away[sizeof(T)*N];
std::memcpy( optimized_away, ptr , sizeof(T)*N );
T* r = ::new( ptr ) T[N];
assert( r == ptr );
std::memcpy( r, optimized_away, sizeof(T)*N );
return r;
}
现在只需
void Manager::byteArrayToDoubleArray(byte ch[]) {
double* pdouble = laundry_pods<double, 8>(ch);
}
pdouble
是指向ch
内存的指针,该指针被解释为8个double的数组。 (它不是它的副本,它就地解释了这些字节)。
尽管laundry_pods
似乎在复制字节,但g ++和clang都将其优化为二进制noop。 看似字节的复制是一种避免C ++标准中的别名限制和对象生存期规则的方法。
它依赖于没有额外记账开销的Pod数组(C ++实现是可以自由执行的;我不知道这样做。这是非静态的断言双重检查的内容),但是它返回了一个指向真正诚实的指针。善良数组的两倍。 如果要避免这种假设,可以改为将每个doulbe
创建为单独的对象。 但是,它们不是数组,因此就标准而言,非数组上的指针算法充满了麻烦。
术语“洗钱”的使用与解决混叠和对象生存期要求有关。 该函数在运行时不执行任何操作 ,但是在C ++抽象机中,该函数将占用内存并将其转换为二进制相同的内存,该内存现在是一堆double
。
进行这种“转换”的技巧是始终将double*
char*
转换为char*
(或unsigned char
或std::byte
)。 从来没有反过来。
您应该能够执行以下操作:
void byteArrayToDoubleArray(byte* in, std::size_t n, double* out)
{
for(auto out_bytes = (byte*) out; n--;)
*out_bytes++ = *in++;
}
// ...
byte ch[64];
// .. fill ch with double data somehow
double res[8];
byteArrayToDoubleArray(ch, 64, res);
假设byte
类型是char
或unsigned char
或std::byte
的别名。
由于代码(sizeof(ch) / sizeof(*ch))
对于未定义大小的数组没有意义,因此我无法完全确定您要在此处实现的目标。
如果您有一个字节数组(POD数据类型;类似typedef char byte;
东西),那么这个最简单的解决方案是reinterpret_cast:
double *result = reinterpret_cast<double*>(ch);
只要ch[]
有效且包含至少64个字节,就可以使用result [0] .. result [7]。 请注意,此构造不会生成代码。 它告诉编译器result [0]对应于ch [0..7],依此类推。 对result []的访问将导致对ch []的访问。
但是您必须知道ch[]
的元素数量才能计算result
中有效的双元素数量。
如果您需要一个副本(例如-因为ch []是一个临时数组),则可以使用
std::vector<double> result(reinterpret_cast<double*>(ch), reinterpret_cast<double*>(ch) + itemsInCh * sizeof(*ch) / sizeof(double));
因此,如果ch []是一个包含64个项目的数组,而一个字节实际上是一个8位值,则
std::vector<double> result(reinterpret_cast<double*>(ch), reinterpet_cast<double*>(ch) + 8);
将提供包含8个double值的std::vector
。
还有一种使用联合的可能方法:
union ByteToDouble
{
byte b[64];
double d[8];
} byteToDouble;
8个double值将占用与64字节值相同的内存。 因此,您可以将字节值写入byteToDouble.b[]
并从byteToDouble.d[]
读取结果的byteToDouble.d[]
值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.