代码之家  ›  专栏  ›  技术社区  ›  vxs8122

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

  •  10
  • vxs8122  · 技术社区  · 10 年前

    我正试着通过右移十六进制来测试我的电脑是执行算术右移还是逻辑右移 FFFFFFFF 通过 1 .

    我知道一个整数 -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 回复  |  直到 10 年前
        1
  •  9
  •   WhozCraig    10 年前

    这不是一个假设。什么 类型 你觉得呢 0xffffffff 是根据C标准, 6.4.4.1整数常量 这个 类型 的表达式 十六进制 常量(前面加 0x )是可适用地保持所表示值的以下值中的第一个:

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

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

    我的结论可能不太清楚 整数 在你的平台上是32位。事实上,如果不是因为 第一 行,算术右移的值 -1 。该转换的结果,转储为 %x 0xFFFFFFFF 整数 本机64位,应转储 0xFFFFFFFFFFFFFFFF 相反如果没有这些先验知识 0xFFFFFFFF(0xFFFFF) 可以假设,因为它可以很好地表示为标准签名 整数 宽度为64位(63+1),带值 0x00000000FFFFFFFF 由此产生的转变将产生与您现在看到的相同的输出,从而引入上述假设的替代方案。

        2
  •  6
  •   Yu Hao    10 年前

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

    从C11§6.4.4.1整数常量

    整数常量的类型是其值可以 代表。

    enter image description here

    第一次的输出 printf 这条线表明 int 在您的计算机上为32位。因此,它不能代表 0xffffffff(0xffffff) ,它必须是无符号的。