使用C按位运算的行为

时间:2014-05-02 09:34:49

标签: c bit-manipulation

我目前正在尝试使用C中的按位运算,我正在尝试理解为什么此代码会为变量a和变量b打印不同的值。 我知道32位移位会溢出1变量(这是一个普通的int),但我的理解是它在两种情况下都应该打印0。

相反,它打印的内容似乎是unsigned int a的随机数和unsigned long int b的0值。

#include <stdio.h>

int main(){
  printf("%lu %lu\n",sizeof(int), sizeof(long int));
  unsigned int a = 1 << 32;
  unsigned long int b = 1 << 32;
  printf("%u %lu\n", a, b);
  return 0;
}

示例输出:

4 8
374588997 0

我错过了什么?

修改

现在我只尝试31位移位,编译器没有给我任何警告。 来源:

#include <stdio.h>

int main(){
  int shift = 31;
  unsigned long int b = 1 << shift;
  printf("%lu\n", b);
  return 0;
}

它输出18446744071562067968,实际上不是2 ^ 31。任何线索?

3 个答案:

答案 0 :(得分:0)

第一个a是随机的,因为移位数大于类型的长度。这是未定义的行为:

/tmp/test.c: In function 'main':
/tmp/test.c:5:6: warning: left shift count >= width of type [enabled by default]
      unsigned int a = 1 << 32;
      ^

现在b被声明为long int,但其值是使用32位逻辑计算的,因为默认情况下1是int

/tmp/test.c:6:8: warning: left shift count >= width of type [enabled by default]
      unsigned long int b = 1 << 32;
      ^

b的正确表达式为:

unsigned long int b = 1L << 32;

编辑回答您的新问题:

在C中,默认情况下为1 signed int因此1 << 31为负数-2147483648。现在这个数字被转换为64位,它变成0xffffffff80000000(-2147483648作为signed long int),最后它的签名被丢弃。这就是为什么你得到18446744071562067968这是0xffffffff80000000。

答案 1 :(得分:0)

更改您的代码如下

#include <stdio.h>

int main(){
  int shift = 31;
  unsigned long int b = 1LU << shift; /* or 1U << shift */
  printf("%lu\n", b);
  return 0;
}

在您的系统上似乎long int是64位。

你得到的结果是负数并试图将它存储到64位无符号,导致奇怪的数字。

P.S。 18446744071562067968 = FFFFFFFF80000000

答案 2 :(得分:-1)

您的代码按预期工作(gcc 4.6.3 on 12.04LTS)。但它会产生一些关于移位数大于类型宽度的警告。

编译给出:

Test.c: In function ‘main’:

Test.c:5:5: warning: left shift count >= width of type [enabled by default]

Test.c:6:4: warning: left shift count >= width of type [enabled by default]

运行输出:

4 8

0 0

祝你好运!