數據傳輸中,經常會與下位機通訊,用串口或者tcp,經常會遇到如何把結構體轉換成二進制數據的問題,在此提供兩個常用的方法,以供參考。
首先定義結構體,注意保證字節對齊:
#pragma pack(push, 1)
struct Student {
quint8 id;
int stature;
};
#pragma pack(pop)
創建一個學生對象並賦值:
Student stu1;
stu1.id = 6;
stu1.stature = 184;
創建一個QByteArray對象,用來承載數據:
QByteArray byteArray;
現在stu1對象中有兩個值,一個8位的整型數據,一個是32位的整型數據。要把他們變爲二進制存儲進QByteArray中:
方法一: 用 QByteArray &append(const char *s, int len)
直接在後面append想要的數據,那麼數據會按照append的順序逐個添加至數據末端。
byteArray.append(reinterpret_cast<char *>(&stu1), sizeof(Student));
之所以用 reinterpret_cast<A>(B),只是用來消除編譯器警告,其實就是類型轉換,把結構體對象強制轉成char *類型,並且提供結構的長度(數據對齊不對齊會影響該值)
我們打印一下看到:
qDebug() << "we get:" << byteArray.toHex();
>> we get: "06b8000000"
可以看到06是第一個8位的整型 ,後面是32位的整型,184 = 0x000000B8,注意這裏低位在前,高位在後。
方法二:用 memcpy(void * __restrict__ _Dst,const void * __restrict__ _Src,size_t _Size)
此時需要注意,拷貝到的目標一定是已經初始化的,並且已經有足夠的空間容納被拷貝的對象,否則會溢出造成崩潰!
byteArray.resize(sizeof(Student));
memcpy(byteArray.data(), &stu1, sizeof(Student));
我們再次打印一下,結果與之前的一致。
如果結構體中有float,double等,也可以用上述方法進行轉換。
最後附上全部代碼:
#pragma pack(push, 1)
struct Student {
quint8 id;
int stature;
};
#pragma pack(pop)
Student stu1;
stu1.id = 6;
stu1.stature = 184;
QByteArray byteArray;
#if 0
byteArray.append(reinterpret_cast<char *>(&stu1), sizeof(Student));
#else
byteArray.resize(sizeof(Student));
memcpy(byteArray.data(), &stu1, sizeof(Student));
#endif
qDebug() << "we get:" << byteArray.toHex();