[英]How do I extract specific 'n' bits of a 32-bit unsigned integer in C?
[英]Extract upper and lower word of an unsigned 32-bit integer
要提取無符號32位整數的高位字和低位字,並將每個字存儲在單獨的uint16_t變量中,我執行如下操作( nbr是無符號的32位整數):
uint16_t lower_word = (uint16_t) nbr & 0x0000FFFF; // mask desired word
uint16_t upper_word = (uint16_t) ((nbr & 0xFFFF0000) >> 16); // right-shift after masking
顯式轉換為uint16_t是不必要的嗎? 還有什么其他更有效的方法,如果有的話,你建議獲得所需的結果而不是這種方法嗎?
uint16_t lower_word = (uint16_t) nbr;
uint16_t upper_word = (uint16_t) (nbr >> 16);
面具沒用
cast是必要的,否則編譯器可能會產生警告
{編輯以考慮Lundin / Eric Postpischil的評論}
例如, gcc -Wconversion
會在沒有gcc -Wconversion
生成警告
C型系統既微妙又危險。 顯式轉換可能是必要的,也可能不是必需的。 在(uint16_t) nbr & 0x0000FFFF
情況下,假設32位CPU,轉換是不正確的。
你在行動發生前施放。 意味着操作數nbr
將由nbr
轉換顯式轉換,然后通過隱式整數提升立即隱式轉換為int
。 結果將是int
類型,已簽名。 在這種情況下無害但在其他情況下會引起麻煩。 通過使用不正確的uint32_t
,您從uint32_t
創建了一個signed int
,這不是意圖。
總的來說,您需要了解隱式類型促銷規則 。
雖然,在分配回uint16_t
時會有一個隱含的左值轉換,大部分時間都會節省一天。
另請注意, 0x0000FFFF
是危險的風格。 無論您在值之前放置多少個零,Hex文字都是值適合的類型。 在這種情況下,它是簽名的int
。 在16位系統上, 0x0000FFFF
將給出int
但0x00008000
將給出unsigned int
。 (例如,檢查這個奇怪的bug: 為什么0 <-0x80000000? )
最佳實踐,堅固耐用,可移植,符合MISRA-C的代碼,是完全不包含任何隱式轉換的代碼:
uint32_t nbr = ...;
uint16_t lower_word = (uint16_t) (nbr & 0xFFFFUL);
uint16_t upper_word = (uint16_t) ((nbr >> 16) & 0xFFFFUL);
假設nbr
已知為uint32_t
,否則最好在強制轉換之前將該操作數強制轉換為uint32_t
。
在這種特定情況下,掩碼並不是必需的,但在一般情況下,例如從uint32_t
屏蔽掉4個字節時。
不,你不需要類型轉換,我建議不要使用一個。 這是因為它具有比&運算符更高的優先級,因此nbr首先轉換為uint16_t然后被屏蔽。 這也是為什么第二行在沒有附加括號的情況下不起作用的原因。
除此之外,代碼很好,並沒有真正的理由使用不同的方法。 您也可以先執行shift,然后屏蔽該值,但生成的匯編代碼應該完全相同。
如果您需要在代碼中多次重復此操作,還有另一種方法可以使用聯合:
typedef union _uplow
{
struct _reg {
uint32_t low : 16;
uint32_t up : 16;
} reg;
uint32_t word;
} uplow;
聲明您的變量如下:
uplow my_var;
my_var.word = nbr;
像這樣使用它:
printf ("Word : 0x%x\n Low : 0x%x\n Up : 0x%x\n", my_var.word, my_var.reg.low, my_var.reg.up);
輸出:
Word : 0xaaaabbbb
Low : 0xbbbb
Up : 0xaaaa
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.