我正在尝试通过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
答案 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整数常量
整数常量的类型是其值可以在其中的第一个相应列表 代表。
第一行printf
行的输出表明您的计算机上int
为32位。因此,它不能代表0xffffffff
,它必须是无符号的。