我目前正在尝试使用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。任何线索?
答案 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
祝你好运!