在我正在使用的圖書館中,我發現了這樣的結構:
typedef struct {
uint16_t id;
uint16_t len;
union {
uint8_t data[0];
uint16_t data16[0];
uint32_t data32[0];
}
} packet_t;
所以這是一個具有靈活長度資料的資料包,可以訪問每個字長。
但是標準說物件不能有零大小,因此編譯它會引發警告(“ISO C 禁止零大小陣列”)。
我在 gcc 中編譯代碼,因此由于其擴展,這個零大小的陣列 hack 會做得很好。但是有什么辦法可以讓我真正“迂腐”嗎?由于聯合,彈性陣列成員沒有幫助。
如果我只是扔掉多位元組資料成員會很簡單,但我想盡可能多地保留它們,因為庫中的某些函式依賴于這些。
起初我以為我可以使用單一大小的陣列,但我不確定是否根本沒有副作用。有什么建議嗎?
uj5u.com熱心網友回復:
生成帶有 -pedantic 標志編譯的東西并非不可能。但是我認為沒有 C11,您無法在語法上獲得完全相同的語意。
轉換后packet_t可能看起來像這樣
typedef union packet_t {
struct { uint16_t id; uint16_t len; };
struct { uint16_t id8; uint16_t len8; uint8_t data[]; };
struct { uint16_t id16; uint16_t len16; uint16_t data16[]; };
struct { uint16_t id32; uint16_t len32; uint32_t data32[]; };
} packet_t;
需要匿名結構 (C11) 將欄位作為packet_t. 這就是使p->id仍然有效的原因。其他id*和len*欄位是虛擬的,因為靈活的陣列成員可能不是結構的唯一成員。它們的作用是根據聯合的共同初始序列保證使訪問格式良好。
看著它,我不禁覺得你最好data完全放棄多個領域。一個uint8_t靈活的陣列成員可以包含其他兩個可能包含的任何內容。
uj5u.com熱心網友回復:
在 C99 之前,沒有符合標準的方式。在 C99 中,
typedef struct {
uint16_t id;
uint16_t len;
uint8_t data[];
} packet_t;
是做靈活長度結構的合法方式。
union無論如何,您幾乎是無用的合成糖:無論如何,您都需要從外部了解型別,而 C 沒有型別限制,因此無論您是撰寫packet.data16[2]還是uint16_t* data = packet.data; data[2]制作幾乎沒有什么區別。
沒有符合標準的方法來保留union具有不同成員長度的型別陣列作為最后一個元素。
uj5u.com熱心網友回復:
如果您使用 C99 之前的編譯器,那么一個簡單的常用技巧是將大小設定為 1。當然,在處理它時,您還需要將大小加/減 1
typedef struct {
uint16_t id;
uint16_t len;
union {
uint8_t data[1];
uint16_t data16[1];
uint32_t data32[1];
}
} packet_t;
也可以看看
- 與 C 中的 C 靈活陣列成員互操作的正確方法是什么?
- 為什么有些結構以大小為 1 的陣列結尾?
- 靈活陣列成員在 C 中有效嗎?
- BITMAPIINFO 結構的 bmiColors 欄位
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/355206.html
下一篇:在c中插入鏈表時的值錯誤
