[英]Serializing/deserializing a bitfield structure in c++
我有一個
typedef struct {
uint32_t Thread: HTHREAD_BUS_WIDTH;
uint32_t Member: 3;
uint32_t Proxy:3;
// Other members, fill out 32 bits
} MyStruct;
我必須從一個系統傳輸到另一個系統作為包含 32 位字的緩沖區的一項。
序列化結構以及反序列化它的最佳方法是什么? “最佳”在這里意味着安全鑄造,沒有不必要的復制。 對於一個鑄造方向,我發現(作為成員函數)
int &ToInt() {
return *reinterpret_cast<int *>(this);}
是否有類似的有效轉換,即從 integer 到 MyStruct; 最好的成員是 function?
如何定義哪個位表示哪個字段? (甚至可能是反序列化發生在另一個程序、另一種語言、小/大端系統中?
如何定義哪個位表示哪個字段?
你不能。 您無法控制位域的布局。
“最佳”在這里意味着安全鑄造,沒有不必要的復制。
沒有可以避免復制的便攜式安全演員。
序列化位域的一種可移植方法是按所需順序手動轉換為 integer。 例如:
MyStruct value = something;
uint32_t out = 0;
out |= value.Thread;
out << HTHREAD_BUS_WIDTH;
out |= value.Member;
out << 3;
out |= value.Proxy;
在所示示例中,最低有效位包含字段Proxy
,而其他字段在更高有效位中相鄰。
當然,為了正確序列化這個生成的 integer,就像序列化任何 integer 一樣,您必須考慮字節順序。 integer 的序列化可以通過重復移動 integer 並將字節按重要性順序復制到數組中來實現。
如果您需要從可能具有不同字節順序的其他系統讀取,則不能依賴可移植位域。 一種解決方案是“擴展”您的結構,以便每個字段在“傳輸”緩沖區中序列化為 32 位值。 一個安全的實現可能是這樣的:
typedef struct {
uint32_t Thread: HTHREAD_BUS_WIDTH;
uint32_t Member: 3;
uint32_t Proxy:3;
// Other members, fill out 32 bits
std::vector<uint32_t > to_buffer() const;
} MyStruct;
to_buffer()的實現:
std::vector<uint32_t > MyStruct::to_buffer() const
{
std::vector<uint32_t> buffer;
buffer.push_back((uint32_t )(Thread);
buffer.push_back((uint32_t )(Member);
buffer.push_back((uint32_t )(Proxy);
// push other members
return buffer;
}
然后在接收端你可以做“緩沖區”來構建。
如果您不想擴展不使用 32 位的字段,您始終可以通過移位和屏蔽位來實現自己的打包 function,例如:
uint32_t menber_and_procy = (Member << 3) | proxy; // and so one for other members.
它更容易出錯。
根據我自己的經驗,如果通信帶寬不是問題,那么依靠“類似文本”的內容是更好的選擇(沒有字節序問題並且非常容易調試)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.