C语言中的右移位运算符

3

我得到了以下的代码:

int main(int argc, char *argv[])
{
    char c = 128;

    c = c >> 1;

    printf("c = %d\n", c);

    return 0;
}

在32位Windows XP上运行上述代码,我得到了结果:-64。为什么会是-64呢?

4
提示:在代码行 char c = 128; 后面添加一行 printf("before shift c = %d\n", c); - Raymond Chen
4个回答

9
因为char类型在你使用的C实现中是有符号的8位整数。如果你试图将值128存储在其中,它实际上会变成-128。
对应的二进制位如下:
10000000

负数进行位移操作时,符号位会被保留(因为你的实现采用了算术位移):

11000000

结果是-64。

3
但是你应该澄清在那个特定平台上 char 是有符号的。此外,你应该澄清标准没有为右移负值指定任何特定行为。 - Oliver Charlesworth
@OliCharlesworth:是的,你说得对。这个http://en.wikipedia.org/wiki/C_data_types和这个http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B有关于标准中具体信息。 - Guffa

3
C标准并未规定char是有符号还是无符号的。在这种情况下,看起来你得到的是一个带有范围从-128到+127的有符号char。将其赋值为128会循环回来,留下-128,因此c>>1为-64。
如果将c指定为“unsigned char”,c>>1将为64。
正如注释所说,对负值进行右移操作在标准中是未定义的,因此它只是幸运地出现为-64。

2
+1 对于第一部分。但是您应该澄清右移负值是实现定义的。 - Oliver Charlesworth

0

变量c是有符号的。将声明更改为unsigned char c...将得到一个结果为64。


0

您正在使用默认为有符号的类型char。有符号的char范围为-128到127,这意味着char c = 128实际上将c设置为-128。(这是因为大多数处理器使用二进制补码表示负数)因此,当您向右移位时,您会得到-64。

底线是,在进行位操作时,请使用无符号类型以获得您期望的结果。


关于“默认情况下是有符号的”:不是的,这取决于具体情况。对于 IBM C++ 编译器(用于 AIX),它与之前遇到的所有其他环境都不同(一个跨平台的 C++ 应用程序)。尽管如此,这是唯一需要的更改。 - Peter Mortensen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接