问题描述
我正在尝试从一个字节数组创建一个双精度数组的别名。但它的行为恰好与我预期的不同。 字节数组存储 - 传感器代码 (int) 后跟位置数据 (double[3])。这是我试过的
std::byte mSensorData[sizeof(int32_t) + 3 * sizeof(double)];
int32_t& mSensorCode = *((int32_t*) &mSensorData);
double (& mLocation)[3] = *((double (*)[3])&mSensorData + sizeof(int32_t));
/* some code,byte* gpsData contains location data */
memcpy(mLocation,gpsData,sizeof(mLocation));
DEBUG(std::cout<<mSensorCode <<std::endl;)
DEBUG(std::cout<<mLocation[0] <<std::endl;)
DEBUG(std::cout<<mLocation[1] <<std::endl;)
DEBUG(std::cout<<mLocation[2] <<std::endl;)
DEBUG(std::cout<<*((int*)&mSensorData[0]) <<std::endl;)
DEBUG(std::cout<<*((double*)&mSensorData[4]) <<std::endl;)
DEBUG(std::cout<<*((double*)&mSensorData[12]) <<std::endl;)
DEBUG(std::cout<<*((double*)&mSensorData[20]) <<std::endl;)
我得到的结果:
120
37.422
-122.084
16.6551
120
0
0
0
解决方法
我无法对您的帖子发表评论,因此我将添加另一个答案:D。
该版本有效,因为现在您正确地进行了转换。
mSensorData + sizeof(int32_t))
现在将使您在 sizeof(int32_t)
的右侧获得 mSensorData
个字节(请注意,发生这种情况是因为 mSensorData
的类型为 byte ..它实际上将您带入 {{1} } 字节向右,但 sizeof(int32_t) * sizeof(std::byte)
的大小为 1)。
它以前不起作用,因为 std::bytes
是完全不同的东西。首先,(double (*)[3])&mSensorData + sizeof(int32_t)
与此无关。您将最终获得堆栈地址并开始转换堆栈上的内容。但即使那不存在,&
仍然是错误的。它的作用是将 (double (*)[3])mSensorData + sizeof(int32_t)
转换为 3 个双精度数组,然后将指针 mSensorData
向右移动。注意到区别了吗?现在你的指针是 sizeof(int32_t) * 3 * sizeof(double)
类型,所以它的任何算术都会移动你的指针 double (*)[3]
字节
抛开可怕的别名违规问题,以及您真的、真的不能这样做的事实:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-20-7ca687ee0af3> in <module>
14 import pandas as pd
15
---> 16 rols = RollingOLS(X,y,window=60)
17 rres = rols.fit()
18 params = rres.params
/opt/conda/lib/python3.8/site-packages/statsmodels/regression/rolling.py in __init__(self,endog,exog,window,min_nobs,missing,expanding)
445 expanding=False
446 ):
--> 447 super().__init__(
448 endog,449 exog,/opt/conda/lib/python3.8/site-packages/statsmodels/regression/rolling.py in __init__(self,weights,expanding)
154 self.k_constant = k_const
155 self.data.const_idx = const_idx
--> 156 self._y = array_like(endog,"endog")
157 nobs = self._y.shape[0]
158 self._x = array_like(exog,"endog",ndim=2,shape=(nobs,None))
/opt/conda/lib/python3.8/site-packages/statsmodels/tools/validation/validation.py in array_like(obj,name,dtype,ndim,maxdim,shape,order,contiguous,optional)
145 if arr.ndim != ndim:
146 msg = "{0} is required to have ndim {1} but has ndim {2}"
--> 147 raise ValueError(msg.format(name,arr.ndim))
148 if shape is not None:
149 for actual,req in zip(arr.shape,shape):
ValueError: endog is required to have ndim 1 but has ndim 2
您的目的是在 (double (*)[3])&mSensorData + sizeof(int32_t)
开始后为 sizeof(int32_t)
字节创建别名。
然而,这不是指针添加在 C++ 中的工作方式。毕竟,鉴于以下情况:
mSensorData
int *p;
int *q=p+1;
是否不指向 q
之后的 1 个字节。 p
指向 q
指向的位置之后的 next 整数。在 64 位平台上,p
指向 q
之后的 8 个字节。
实际上,当您向指针添加某些内容时,添加的任何内容(包括减法)都会乘以 p
的指针指向的内容。
因此,上述加法的结果是sizeof
开头后的sizeof(int32_t)*sizeof(double (*)[3])
字节的别名。
为了进行预期的计算,您需要先转换为 mSensorData
,执行加法,然后转换为 char *
。
你在做什么似乎有点太复杂了。您只需要将其余的缓冲区从 char*
解释为您需要的类型。例如:
#include <iostream>
#include <cstring>
int main() {
int size = sizeof(int32_t) + 3 * sizeof(double);
char data[size];
memset(data,size);
data[0] = 1;
int first_int = *(int*)data;
double *doubles = (double*)(data + sizeof(int32_t));
printf("%d %f %f %f \n",first_int,doubles[0],doubles[1],doubles[2]);
}
对我来说效果很好。 1 0.000000 0.000000 0.000000
如果你愿意,你可以使用 reinterpret_cast 而不是 c 风格的强制转换 double *doubles = reinterpret_cast<double *>(data + sizeof(int32_t));
,但你只是将缓冲区重新解释为双精度缓冲区而不是字符缓冲区
知道为什么这样做吗?
gps.h
#ifndef GPS_H
#define GPS_H
#include <cstddef>
#include <stdint.h>
class GPS
{
std::byte mSensorData[sizeof(int32_t) + 3 * sizeof(double)];
int32_t& mSensorCode = *((int32_t*) mSensorData);
double (& mLocation)[3] = *((double (*)[3])(mSensorData + sizeof(int32_t)));
public:
GPS();
int processData(const std::byte* gpsData);
int getLocationData(std::byte* buffer) const;
};
#endif
gps.cpp
#include "gps.h"
#include "common.h"
#include <cstring>
#include <exception>
GPS::GPS(){
mSensorCode = LOCATION;
}
int GPS::processData(const std::byte* gpsData){
try {
gpsData += sizeof(int32_t);
memcpy(mLocation,gpsData,sizeof(mLocation));
DEBUG(std::cout<<"Buffer Content" <<std::endl;)
DEBUG(std::cout<<*((int*)&mSensorData[0]) <<std::endl;)
DEBUG(std::cout<<*((double*)&mSensorData[4]) <<std::endl;)
DEBUG(std::cout<<*((double*)&mSensorData[12]) <<std::endl;)
DEBUG(std::cout<<*((double*)&mSensorData[20]) <<std::endl;)
DEBUG(std::cout<<"Data Content" <<std::endl;)
DEBUG(std::cout<<mSensorCode <<std::endl;)
DEBUG(std::cout<<mLocation[0] <<std::endl;)
DEBUG(std::cout<<mLocation[1] <<std::endl;)
DEBUG(std::cout<<mLocation[2] <<std::endl;)
}catch(std::exception& ex) {
DEBUG(std::cout << "GPS::processData ex:" << ex.what() << std::endl;)
}
return sizeof(mSensorData);
}
int GPS::getLocationData(std::byte* buffer) const{
memcpy(buffer,&mSensorData,sizeof(mSensorData));
return sizeof(mSensorData);
}
结果
Buffer Content
120
37.422
-122.084
0.0962061
Data Content
120
37.422
-122.084
0.0962061