为什么-1>> 1和0xFFFFFFFF>> 1产生不同的结果?

时间:2014-07-10 02:29:15

标签: c bitwise-operators bit-shift

我正在尝试通过FFFFFFFF右移16进制1来判断我的PC是执行算术还是逻辑右移。

我知道整数-1在十六进制中读为FFFFFFFF,因为它是1的二进制补码。将-1右移1会产生FFFFFFFF并显示PC执行算术右移。

但如果我只输入0xFFFFFFFF >> 1,则会产生7FFFFFFF并显示PC执行了逻辑右移。为什么会这样?请参阅下面产生结果的代码:

#include    <stdlib.h>
#include    <stdio.h>

int main ( int argc, char *argv[] )
{
    printf ( "%x >> 1 = %x\n", -1, -1 >> 1 );
    printf ( "%x >> 1 = %x\n", 0xffffffff, 0xffffffff >> 1 );

    return EXIT_SUCCESS;
}

该计划的输出是:

ffffffff >> 1 = ffffffff
ffffffff >> 1 = 7fffffff

2 个答案:

答案 0 :(得分:8)

这不是假设。您认为0xffffffff是什么类型?根据C标准, 6.4.4.1整数常量十六进制常量表达式的类型(以0x开头)是以下第一个可以适用的代表值:

int
unsigned int
long int
unsigned long int
long long int
unsigned long long int

在您的平台上,0xFFFFFFFF不能表示为int,因为int是32位,只有31位表示signed int中的数量(标准规定一位保留用于符号)。因此使用下一个类型unsigned int。因此,在移位操作中不存在符号位,因此是逻辑而不是算术。

我的结论int在您的平台上是32位可能并不明显。事实上,如果不是第一个行,那么我无法做出这样的假设,即算术右移-1的值。转换为%x的转换结果为0xFFFFFFFF。如果int是本机64位,则应转储0xFFFFFFFFFFFFFFFF。如果没有该先验知识,则不能假设0xFFFFFFFF的单一类型结论,因为它可以表示为宽度为64位(63 + 1)的标准符号int,其值为0x00000000FFFFFFFF 。由此产生的移位将产生您现在看到的相同输出,从而引入上述假设的替代方案。

答案 1 :(得分:6)

您的主要问题是:0xffffffff未签名?

来自C11§6.4.4.1整数常量

  

整数常量的类型是其值可以在其中的第一个相应列表   代表。

     

enter image description here

第一行printf行的输出表明您的计算机上int为32位。因此,它不能代表0xffffffff,它必须是无符号的。