繁体   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