我正在使用返回字节数组的串行设备。 在此数组中是存储在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;
将数组映射到此结构的最佳方法是什么?从串行设备接收的数组中的顺序与结构匹配。
答案 0 :(得分:4)
首先,您使用类C语法对结构中数据类型的描述是不明确的。它没有告诉我们short
或char
类型的大小,也没有告诉我们数据的字节顺序! short int
不必是16位宽,char
也不是8位!至少,您应该使用fixed width integer types或它们的Qt等价物,并指定它们的字节顺序。
此外,typedef struct
是C-ism,在C ++中是不必要的。放下typedef
。
假设有一个大端数据包,unsigned short
表示uint16_t
而unsigned 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());