为什么我在左移位的不同实现中有这种不同的行为?

时间:2016-05-25 22:10:35

标签: c bit-shift

我的代码的目的是在我的int(32位)表示的右边创建一个n个零的掩码。我的方法是首先将负数存储在变量中,然后将其向左移动n个空格以向右移动n个零。代码如下:

int mask(int n){
  int neg1=(1<<31)>>31;
  int mask=neg1<<n;
  return mask;
}

尽管如此,当n为32时,我想获得值0x0,但我得到的是0xffffffff(neg1)。当我转换到变量时会发生这种情况。但是当我转向恒定本身时,它就像一个魅力。新代码将是:

mask=0xffffffff<<n;

尽管如此,我不允许使用超过8位的常量。所以我需要存储在另一个变量中的值。有人可以告诉我为什么会这样,我该如何解决?

非常感谢你!

1 个答案:

答案 0 :(得分:1)

当尝试向左移动到32位int的符号位时,OP的代码调用未定义的行为。

  

E1的结果&lt;&lt; E2是E1左移E2位位置;腾出的位用零填充。 ...如果E1具有有符号类型和非负值,并且E1×2E2在结果类型中可表示,那么这就是结果值;否则,行为未定义。 C11§6.5.74

而是使用无符号类型来避免移位为31的错误定义的行为.32位unsigned上的32+移位也是一个问题。

一种简单的方法使用更广泛的类型。

#include <stdio.h>
#include <inttypes.h>

uint32_t mask32(int n) {
  return 0 - (1ull << n);
}

int main(void) {
  for (int i=0; i<=32; i++) {
    printf("%2d %lX\n", i, (unsigned long) mask32(i));
  }
}

输出

 0 FFFFFFFF
 1 FFFFFFFE
 2 FFFFFFFC
 ...
29 E0000000
30 C0000000
31 80000000
32 0