2014-05-24 88 views
2

我有一個uint8_t陣列,我需要從前面的4個元素,32位,創建一個size_tuint32_t在我的機器上)。從uint8_t數組的四個元素獲取uint32_t的優雅方式?

實施例的非工作代碼:

uint8_t array[8]; 
array[0] = 128; 
array[1] = 128; 
array[2] = 0; 
array[3] = 0; 
size_t size = array[0]; //results in 128 
size = *array; //also results in 128 

該數組的前四個指數的字節是80 80 00 00

我希望size_t通過讀取該數組中最前面的4個字節(小端)來生成128 + 256 * 128。有沒有辦法使size_t初始化直接讀取這4個字節,就好像該數組是任何舊的內存塊,而不必手動添加和乘法以找到我想要的值?

回答

6

要以便攜的方式(即獨立於endian)使用shift操作符。像

uint32_t result = 0; 
for(int i=3; i>=0; --i) { 
    result <<= 8; 
    result += array[i]; 
} 
// result now holds the value you desire 
+0

我不知道任何有關這些轉變經營者;這比我說的更好。這會導致機器進行數學運算,但似乎只會相當於複製數位。這會比做我建議的慢,但有一些編譯器標誌檢測endianness? – sudo

+0

不要擔心速度,直到(1)你已經證明你的代碼太慢,並且(2)你已經證明即使開啓了所有的優化。大多數編譯器在優化這種事情方面做得很好。只需循環展開就可以解決這個問題,現代x86機器擁有各種各樣的奇特操作碼,僅用於這種類型的操作。 – dmckee

+0

我得到了兩個基本相當的答案,都很好,但是這個更清潔一點,可擴展性更強,所以我會將其標記爲答案。 – sudo

-1

明白了。當然,我問過之後!

uint32_t size = *((uint32_t*) array); 
+7

除了形成別名問題,我會警告你,如果在大vs-小的endian系統上使用相同的字節序列,* not *就會工作。 – WhozCraig

+0

@WhozCraig在什麼情況下?如果一個big-endian機器使用例如'*((uint32_t *)array)= 8'寫入,它也會讀取*((uint32_t *)數組)作爲8. – sudo

+0

@ 9000代碼你在你的問題中寫的不是獨立於永久性。是的,雙向投擲單向,然後其他方式在任何機器上都可以,但如果您打算對中間表示做任何事情,您需要知道機器如何處理整數表示。 – dmckee

2

東西這是正常的方式:

inline uint32 little_endian_to_uint32(uint8 *p) 
{ 
    return p[0] + p[1] * 0x100ul + p[2] * 0x10000ul + p[3] * 0x1000000ul; 
} 

你的編譯器應該產生的最佳assmebly代碼。

相關問題