将QByteArray中的数据放入Struct中

时间:2016-03-13 15:47:19

标签: c++ arrays qt data-structures

我正在使用返回字节数组的串行设备。 在此数组中是存储在unsigned short和unsigned chars中的值。 我有以下结构:

    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;

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

2 个答案:

答案 0 :(得分:4)

首先,您使用类C语法对结构中数据类型的描述是不明确的。它没有告诉我们shortchar类型的大小,也没有告诉我们数据的字节顺序! short int不必是16位宽,char也不是8位!至少,您应该使用fixed width integer types或它们的Qt等价物,并指定它们的字节顺序。

此外,typedef struct是C-ism,在C ++中是不必要的。放下typedef

假设有一个大端数据包,unsigned short表示uint16_tunsigned char表示uint8_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上,如果升级编译器,包装和结构的大小类型可以而且会改变!所以不要这样做。 AC / C ++ struct声明暗示 nothing 关于数据如何在内存中排列,除了所选择的排列不会导致未定义的行为,并且必须同意其他要求标准(只有几个)。这就是全部。

答案 1 :(得分:-1)

首先,我想说在您要序列化/反序列化并与其他设备交换的结构中打包 unsigned short 类型是不安全的: unsigned short 通常是16位,但你不能保证,它是平台相关的。

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

如果从串口接收的二进制数据保存在QByteArray中并且字节顺序和“unsigned short”类型都可以,那么要在结构上映射QByteArray中的数据,您可以使用下面的代码。请注意,只有在您的结构被打包并且其中没有填充空白时才是正确的,请为编译器使用struct packing技术(请参阅Structure padding and packing)。

QByteArray bArr;
bArr.resize(sizeof(fc_adv_info_t));
// do something to fill bArr with received data
fc_adv_info_t* info=reinterpret_cast<fc_adv_info_t*>(bArr.data());