2014-12-02 125 views
1

假設我有一個充滿數據的緩衝區,並且我已將其從網絡中取出。在緩衝區中投射指針

uint8_t buffer[100]; 

現在想象一下,這個緩衝區有不同的字段。有些是1個字節,有些是2個字節,有些是4個字節。所有這些字段都打包在緩衝區中。

現在假裝我想抓取16位字段中的一個的值。說,在緩衝區中,字段中,儲存像這樣:

buffer[2] = one byte of two byte field 
buffer[3] = second byte of two byte field 

我可以抓住像這樣的值:

uint16_t* p_val; 

p_val = (int16_t*) &buffer[2]; 
or 
p_val = (int16_t*) (buffer + 2); 

printf("value: %d\n", ntohs(*p_val)); 

有什麼不對這種方法?或者我應該注意的對準問題?

+1

兩個問題:字節順序和對齊。前者可能更重要,因爲編譯器應該通過投入更多的代碼來處理後者。但你必須處理自己的Endianness。 – 2014-12-02 20:53:08

+0

假設我從一個以太網數據包獲得了緩衝區,那麼當解引用解決排序問題時,這個ntohs會是什麼? – user1764386 2014-12-02 20:57:44

+1

還有[嚴格的別名](http://stackoverflow.com/a/99010/274261) – ArjunShankar 2014-12-02 20:58:23

回答

2

正如評論中提到的那樣,是的,您提出的方法存在問題。雖然它可能在目標機器上工作,或者它可能發生在特定情況下,但通常在不同的指針類型之間進行轉換並不安全。 (當然也有例外)

要好好地對齊和字節順序考慮,你可以這樣做:

union convert { 
    uint32_t word; 
    uint16_t halfword[2]; 
    uint8_t bytes[4]; 
} convert; 

uint16_t result16; 

memcpy(convert.bytes, buffer + offset, 2); 

/* assuming network byte order: */ 
result16 = ntohs(convert.halfword[0]); 

如果您在數據格式的控制,那麼網絡字節順序是不錯的選擇因爲程序不需要明確地確定,假定或知道它所運行的機器的字節順序。