繁体   English   中英

如何在Arduino C ++中将大小为64的字节数组转换为双精度值列表?

[英]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 charstd::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类型是charunsigned charstd::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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM