C++ 位操作:相似的操作导致不同的结果

C++ 位操作:相似的操作导致不同的结果,c++,c,operators,bit-manipulation,C++,C,Operators,Bit Manipulation,下面这段代码的计算结果与我认为的不符: #include <stdio.h> #include <stdint.h> int main(void) { uint32_t var = 0x55555555; uint32_t res1 = (var & (0x3 << (15*2)) >> (15*2)); uint32_t res2 = (var & (0x3 << (14*2)) >&

下面这段代码的计算结果与我认为的不符:

#include <stdio.h>
#include <stdint.h>

int main(void) {

    uint32_t var = 0x55555555;
    uint32_t res1 = (var & (0x3 << (15*2)) >> (15*2));
    uint32_t res2 = (var & (0x3 << (14*2)) >> (14*2));
    printf("result1 = 0x%08x\n", res1);
    printf("result2 = 0x%08x\n", res2);

    return 0;
}
#包括
#包括
内部主(空){
uint32_t var=0x5555;
uint32_t res1=(var&(0x3>(15*2));
uint32_t res2=(var&(0x3>(14*2));
printf(“result1=0x%08x\n”,res1);
printf(“result2=0x%08x\n”,res2);
返回0;
}
输出:

结果1=0x5555

结果2=0x00000001


有人能解释为什么在执行完全相同的操作时,result1和result2会不同吗?在执行位移位和按位and时,我做了什么不正确?

15*2=30。0x3=2位->设置uint32中的最高位。由于0x3是有符号的,所以这是一个负数。将其下移30位会得到0xfffffff.Of course,如果将0x3向上移动28位,然后再向下移动,则不会发生相同的情况

如果你真的想分别从第31位和第30位以及第29位和第28位挑出两位,我会:

uint32_t res1 = (var >> (15*2)) & 0x3;
uint32_t res2 = (var >> (14*2)) & 0x3;

除了“更正确”之外,这还节省了一个移位。0x3的类型是有符号整数。C标准规定:

E1在该表达式中的结果

(var & (0x3 << (15*2)) >> (15*2))
设置结果整数值的符号位

手术后

(0x3 << (15*2))
(0x3 << (15*2)) >> (15*2)
将产生
var

在第二个表达式中,不设置符号位,而是在操作之后

(0x3 << (14*2)) >> (14*2)

将产生1。

0x3分解
var&(0x3>(15*2)
在较小的运算中,查看中间值,您会发现。如果您想返回前2位,请使用
0x3U。现在这非常有意义!尽管之前的所有答案基本上都说明了相同的事情。我无意中设置了带符号整数常量的符号位。呸!@SudeepMohanty我很高兴。:)只是一个旁注:为了避免问题从有符号文字蔓延到你期望无符号数学的地方,请使用“U”后缀。甚至还有一个相关的MISRA规则。非常感谢!0x3U确实解决了这个问题。我现在明白出了什么问题:)感谢您提供我也同意的这种替代方法。但不幸的是,我无法更改代码的结构:/
(0x3 << (14*2)) >> (14*2)
0x55555555 & 0x3