2017-04-02 188 views
0

我有以下結構的庫:該庫的自定義用戶數據保留

struct frame_meta_data 
{ 
    uint8_t id; 
    uint8_t general_field_1; 
    uint8_t general_field_2; 
    ... 
    uint8_t user_data[16]; 
}; 

而且我希望用戶能夠自定義的數據保存到幀的對象(這是什麼user_data字段用於)。

嘗試投放USER_DATA到自定義結構然而,當:

frame_meta_data cur_frame; 
... 
#define USER_HDR ((struct my_user_header*)cur_frame.user_data) 

我得到以下錯誤:

 
warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing] 
#define USER_HDR ((struct my_user_header*)cur_frame.user_data) 

我如何解決此問題?

在此先感謝。

+1

不要投。使用'memcpy'。 – melpomene

+0

@melpomene它會傷害我的表現... –

回答

1

C標準不允許重新解釋這樣的地址。嚴格的別名意味着編譯器可以自由地假定不同類型的兩個指針永遠不會指向同一個對象,然後根據這些對象進行各種優化。

您的代碼違反了C標準,並因此導致了未定義的行爲。但是你可以修復它。像墨爾波墨涅的意見建議,不投,而是用memcpy

struct my_user_header obj; 
memcpy(&obj, cur_frame.user_data, sizeof obj); 

另外,一些編譯器允許你寫不規範的代碼編譯器選項,如GCC的-fno-strict-aliasing

1

如果您知道自己在做什麼,可以禁用該警告。但是有一個潛在的問題。

假設您要使用的結構包含大於1個字節的內容。例如一個4字節的整數。現在,如果您只是將該user_data字段轉換爲您的結構,那麼int可能不會按照它應該與4字節邊界對齊。這可能會導致某些體系結構中出現運行時異常。

使用memcpy應該可以解決這個問題。並刪除警告。

+0

如果user_data與4對齊,它仍會如此嗎? –

+0

如果user_data與4對齊,則4字節類型不會有任何問題,但8字節類型可能有問題。 – aragaer

1

我懷疑這是因爲您在涉及數據區域的多次訪問中涉及到這個USR_DATA宏表達式的拷貝,並且它讓編譯器感到困惑。或者,您甚至可以將USR_DATA訪問與底層char數組的操作混合在一起。

如果數據區只按照給定的用戶數據類型進行初始化和訪問,則不會出現任何別名。確保你以這種方式使用它。

我將提供一個外部(如在非內聯,外部連接)API函數,給定一個幀的對象,返回一個void *到相關聯的用戶數據:

struct foobar *fbs = (struct foobar *) frame_get_userdata(fr); 

// now work just with fbs 

鑄造不必要;這是我的風格。

根據用戶數據之前的內容,它可能沒有適合任意使用的對齊方式。如果該選項可用,修復該問題的一個簡單方法是將其作爲第一個struct成員。否則,存在各種相當便攜的技巧,涉及在char陣列與各種類型(如long double等)之間建立聯合,或者使用編譯器特定的構造,如使用GCC的__attribute__((aligned))

相關問題