簡體   English   中英

提取無符號32位整數的上下字

[英]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將給出int0x00008000將給出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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM