2010-07-08 64 views
4

如果我有int temp =(1 < < 31)>> 31。温度怎么会变成-1? 我该如何解决这个问题? 谢谢按位移问题

回答

9

默认情况下,Ints是带符号的,这通常意味着高位被保留以指示整数是否为负值。请查阅Two's complement以了解其工作原理的解释。

这里的结果是:

[[email protected]:~]% cat test.c 
#include <stdint.h> 
#include <stdio.h> 

int main(int argc, char **argv[]) { 
    uint32_t uint; 
    int32_t sint; 
    int64_t slong; 
    uint = (((uint32_t)1)<<31) >> 31; 
    sint = (1<<31) >> 31; 
    slong = (1L << 31) >> 31; 
    printf("signed 32 = %d, unsigned 32 = %u, signed 64 = %ld\n", sint, uint, slong); 
} 

[[email protected]:~]% ./test 
signed 32 = -1, unsigned 32 = 1, signed 64 = 1 

注意如何可以通过使用一个“无符号” INT(允许使用所有32位的)来避免这种问题,或者去一个更大的类型,你不要没有溢出。

+0

特别要小心,有符号值的右移是编译器依赖的。所以在这里看到的输出只适用于特定平台,其他平台可能会给出其他结果。 – 2010-07-08 18:46:15

+0

确实如此,但这并不会使使用无符号或更长变量的修复无效。我认为。 – 2010-07-08 19:09:55

1

int被签名。

什么'问题' - 你想做什么?

int i = (1<<31); // i = -2147483648 
i>>31; // i = -1 

unsigned int i = (1<<31); // i = 2147483648 
i>>31; // i = 1 

PS ch是一个不错的命令行“C” intepreter窗户,让你尝试这种东西无需编译,它也给你一个UNIX命令shell。请参阅http://www.drdobbs.com/184402054

5

对于您的情况,表达式中的1是一种带符号的类型 - 所以当您将它升档31时,其符号会发生变化。然后降档导致符号位被复制,并且最终得到一个0xffffffff的位模式。

你能解决这个问题是这样的:

int temp = (1UL << 31) >> 31; 

GCC发出警告这样那样的错误,如果你已经-Wall开启。

+0

我检查了符号扩展的描述,但是我看不到它与OP观察到的现象有何关系。问题是,在他的实现中,右移是算术移位,int是有符号的,长32位。 http://en.wikipedia.org/wiki/Arithmetic_shift – 2010-07-08 17:57:38

+0

@Maciej,看起来你是对的 - 我在这里滥用这个词。我会编辑以澄清这一点。 – 2010-07-08 18:02:13

1

当你做(1<<31),符号位的MSB被设置(变为1)。然后,当你做正确的转变时,它是符号扩展。因此,你得到-1。解决方案:(1UL < < 31)>> 31.

+0

糟糕,Carl已经回答了。 – 341008 2010-07-08 17:55:54

0

位表示在对整数变量执行“such”左移时设置的符号。因此,结果。