Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 将QByteArray中的数据放入结构中_C++_Arrays_Qt_Data Structures - Fatal编程技术网

C++ 将QByteArray中的数据放入结构中

C++ 将QByteArray中的数据放入结构中,c++,arrays,qt,data-structures,C++,Arrays,Qt,Data Structures,我正在使用一个返回字节数组的串行设备。 此数组中的值存储在无符号短字符和无符号字符中。 我的结构如下: typedef struct { unsigned short RPM; //0 unsigned short Intakepress; //1 unsigned short PressureV; //2 unsigned short ThrottleV; //3 unsigned shor

我正在使用一个返回字节数组的串行设备。 此数组中的值存储在无符号短字符和无符号字符中。 我的结构如下:

    typedef struct {
    unsigned short RPM;             //0
    unsigned short Intakepress;     //1
    unsigned short PressureV;       //2
    unsigned short ThrottleV;       //3
    unsigned short Primaryinp;      //4
    unsigned short Fuelc;           //5
    unsigned char Leadingign;       //6
    unsigned char Trailingign;      //7
    unsigned char Fueltemp;         //8
    unsigned char Moilp;            //9
    unsigned char Boosttp;          //10
    unsigned char Boostwg;          //11
    unsigned char Watertemp;        //12
    unsigned char Intaketemp;       //13
    unsigned char Knock;            //14
    unsigned char BatteryV;         //15
    unsigned short Speed;           //16
    unsigned short Iscvduty;        //17
    unsigned char O2volt;           //18
    unsigned char na1;              //19
    unsigned short Secinjpulse;     //20
    unsigned char na2;              //21
} fc_adv_info_t;

将数组映射到此结构的最佳方法是什么?从串行设备接收的数组中的顺序与结构匹配。

首先,我要说的是,在要序列化/反序列化并与其他设备交换的结构中打包未签名的short类型是不安全的:未签名的short通常是16位,但不能保证这一点,它取决于平台

更糟糕的是,如果结构成员没有对齐,编译器就会在结构中插入填充

如果从串行端口接收的二进制数据以QByteArray格式保存,并且字节顺序和“unsigned short”类型都可以,那么要将QByteArray中的数据映射到结构上,可以使用下面的代码。请注意,只有当您的结构已打包且内部没有填充间隙时,才正确,请为编译器使用结构打包技术(请参阅)

QByteArray-bArr;
bArr.resize(sizeof(fc_adv_info));
//做点什么用接收到的数据填充bArr
fc_adv_info_t*info=reinterpret_cast(bArr.data());

首先,您使用类似C的语法描述结构中的数据类型是不明确的。它没有告诉我们
short
char
类型的大小,也没有告诉我们数据的结尾!
short int
不必是16位宽,也不必是
char
总是8位!至少,您应该使用或它们的Qt等价物,并指定它们的endianness

< > >代码> TyPufFrase是C-ISM,C++中不需要。放下
typedef

假设一个大端数据包,
unsigned short
表示
uint16\u t
unsigned char
表示
uint8\u t
,下面是您可以做到的方法:

struct FcAdvInfo { // this structure shouldn't be packed or anything like that!
  quint16 RPM;
  quint16 IntakePress;
  ...
  quint8 LeadingIgn;
  ...

  FcAdvInfo parse(const QByteArray &);
};

FcAdvInfo FcAdvInfo::parse(const QByteArray & src) {
  FcAdvInfo p;
  QDataStream ds(src);
  ds.setByteOrder(QDataStream::BigEndian);
  ds
    >> p.RPM
    >> p.IntakePress
    ...
    >> p.LeadingIgn
    ...
    ;
  return p;
}

最后,如果您的
struct
来自某些C代码,您必须了解它是不可移植的,即使在同一个CPU上,如果您升级编译器,结构类型的打包和大小也会改变!所以不要这样做。C/C++
struct
声明意味着对数据在内存中的排列方式没有任何影响,但所选择的排列方式不会导致未定义的行为,并且必须符合标准的其他要求(只有少数要求)。仅此而已。

假设从线路接收的字节的尾数也与主机尾数匹配:如果需要结构在
QByteArray
的使用寿命内生存,只需使用好的ol'
memcpy
<代码>重新解释\u cast否则(这将节省您的副本,但会将结构的生命周期绑定到QByteArray本身。阅读:更容易击中您的脚)。如果endian不匹配,则需要通过
qFromLittleEndian
qFromBigEndian
(取决于内存中的fomat)手动转换每个字段。是的,请改用
qint16
。是否保证结构是打包的(内部没有填充)?当然!应该考虑结构填充。更新的帖子。应该可以,因为int之间的字符数是偶数(我想)。是的,在这个结构中,只有最后一个字符似乎没有对齐。这是一个错误的建议。重新解释演员阵容是疯狂的。绝对没有理由将接收主机上的数据表示形式限制为与有线格式相同。在大多数情况下,访问数据的成本更高,因为每次使用数据时都必须发出代码来提取和重新对齐数据。您不认为QDataStream需要额外的标题字节吗?据我所知,QDataStream为其元数据添加了4个额外字节。必须澄清的是,QByteArray必须在串行端口的对等端用QDataStream进行序列化,这对于低级设备控制器来说是不可能的。@EvgenyS。数据流不添加自己的头。“QByteArray必须在对等端使用QDataStream进行序列化”,这是错误的
QDataStream
正是针对这种应用程序而设计的。除其他功能外,它还提供了一种可移植的方法来解析和生成C基本类型的面向字节的数据流。@KubaOber打包不是完全可升级的,如果您不假设任何大小,那么这里的
quint16
有什么用?NB
char
始终为1字节。
struct FcAdvInfo { // this structure shouldn't be packed or anything like that!
  quint16 RPM;
  quint16 IntakePress;
  ...
  quint8 LeadingIgn;
  ...

  FcAdvInfo parse(const QByteArray &);
};

FcAdvInfo FcAdvInfo::parse(const QByteArray & src) {
  FcAdvInfo p;
  QDataStream ds(src);
  ds.setByteOrder(QDataStream::BigEndian);
  ds
    >> p.RPM
    >> p.IntakePress
    ...
    >> p.LeadingIgn
    ...
    ;
  return p;
}