2013-09-30 50 views
0

我試圖讀取從網絡接收到的位序列(以預定義的格式),並想知道我們是否需要照顧endianees。從無符號字符中讀取N位時是否會出現endianess問題

例如,預先定義的格式表示,收到了來自最顯著位開始的數據是這樣的

|R|| 11 bits data||20 bits data||16 bits data| where R is reserved and ignored. 

我的問題是,同時提取我要照顧字節序的或者我可以做

u16 first_11_bits = *(u16 *)data & 0x7FF0) >>4 
u32 20_bits_data = *(u32 *)data & 0x000FFFFF) 
+1

你需要使用'&'來掩蔽,而不是'&&'。 – user694733

+1

那些&&可能不會做你認爲他們會的。它們是「邏輯」和「運算符」,而不是按位和(「&」)。 –

+0

我會說是的。如果你從一臺小型機器發送一個數字,然後在大型機器上接收數據,反之亦然。通常發送的數據應該是大端格式 –

回答

0
u16 first_11_bits = *(u16 *)data & 0x7FF0) >>4 
u32 20_bits_data = *(u32 *)data & 0x000FFFFF) 

這是UBdata指向u16或指向u32。它不能指向兩者。這不是一個永久性問題,它只是一個無效的訪問。您必須通過訪問用於寫入的相同指針類型來訪問以進行讀取。無論你如何寫它,這就是你如何閱讀它。然後,您可以對讀回的值執行位操作,這與您寫入的值相同。

出錯的一種方式是編譯器可以自由地假設通過u32 *的寫入不會影響通過u16 *讀取的值。所以寫入可能是內存,但讀取可能來自緩存在寄存器中的值。這已經打破了真實世界的代碼。

例如:

​​

編譯器是免費治療的最後一行是u16 j = i;。它以相同的方式繼續讀取i,並且可以自由地假設寫入u32 *不會影響從u16 *讀取的結果。

+0

嗨大衛,我不確定我是否遵循。「無論你寫的是什麼,你都是這樣讀的。」我不知道它是如何寫的。數據流是我通過無線接收的,我必須以預定義的格式對比特流進行解碼。接收的比特始終是字節對齊的。我可以執行以下操作:u32 first_32_bits = *(u32 *)data; first_11_bits =(first_32_bits &0x7FF0)>> 4; 20_bits_data = first_32_bits&0x000FFFFF –

+0

這取決於你如何寫它,如果你把它寫成'u32',那麼你必須這樣讀,否則不。 –

0

是的,在讀取/寫入外部資源(文件,網絡,...)時,您總是需要考慮字節順序。但它與位操作無關。

直接鑄造(u16 *)data不是便攜式的做事方式。

我建議在執行位操作之前,先將函數轉換爲本機類型。

1

什麼樣的網絡? IP以字節爲單位進行定義,因此無論位流發生在底層的順序如何,都已經從您的位置抽象出來,並且按照您的CPU瞭解它們的順序接收位。這意味着C提供的訪問這些位的抽象是可移植的。考慮在C中向左或向右移動。無論CPU中的字節順序如何,C中的移位方向和語義都不會改變。

所以問題是:數據如何被另一端編碼成一個字節流?然而,另一端編碼數據應該是你解碼的方式。如果他們只將位移入一個字節並通過網絡發送該字節,則不需要關心。如果他們把位放入一個int16然後以網絡字節順序發送,那麼你需要擔心int16的字節順序。如果他們把這些位放入一個int32併發送,那麼你需要擔心int32的字節順序。

相關問題