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

时间:2023-01-14 09:08:07

I am trying to make a test to tell whether my PC performs arithmetic or logical right shift by right-shifting hexadecimal FFFFFFFF by 1.

我试图通过右移十六进制FFFFFFFF来判断我的PC是执行算术还是逻辑右移。

I know that an integer -1 reads as FFFFFFFF in hexadecimal since it is the two's complement of 1. Right-shifting -1 by 1 results in FFFFFFFF and shows the PC performed arithmetic right shift.

我知道整数-1以十六进制读取为FFFFFFFF,因为它是1的二进制补码。右移-1乘以FFFFFFFF并显示PC执行算术右移。

But if I just type in 0xFFFFFFFF >> 1, it resulted in 7FFFFFFF and shows that the PC performed logical right shift instead. Why did that happen? See for the code below that produced the results:

但是,如果我只输入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;
}

The program's output was:

该计划的输出是:

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

2 个解决方案

#1


7  

It is not an assumption. What type do you think 0xffffffff is ? According to the C standard, 6.4.4.1 Integer constants, the type of the expression of a hexadecimal constant (preceded with 0x) is the first of the following which can applicably hold the represented value:

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

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

On your platform, 0xFFFFFFFF cannot be represented as int because int is 32 bits and only 31 bits express quantity in signed int (the standard dictates one bit is reserved for sign). The next type, unsigned int, is therefore used. Therefore no sign bit is present to extended with the shift operation, which is thereby logical rather than arithmetic.

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

It may not be apparent how I concluded int was 32 bits on your platform. Indeed I could not make that assumption were it not for the first line, which arithmetic-right-shifts the value of -1. The result of that shift, dumped as %x, was 0xFFFFFFFF. Had int been native 64-bits that should dump 0xFFFFFFFFFFFFFFFF instead. Without that prior knowledge, no single type conclusion of 0xFFFFFFFF could be assumed since it may well be representable as a standard signed int of width 64-bits (63+1) with value 0x00000000FFFFFFFF. The resulting shift would produce the same output you see now, thereby introducing an alternative to that postulated above.

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

#2


6  

Your main question is: is 0xffffffff unsigned?

你的主要问题是:0xffffffff是无符号的吗?

From C11 §6.4.4.1 Integer constants

从C11§6.4.4.1整数常量

The type of an integer constant is the first of the corresponding list in which its value can be represented.

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

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

The output of your first printf line suggests that int is 32-bit on your machine. Thus it can not represent 0xffffffff, it must be unsigned.

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

#1


7  

It is not an assumption. What type do you think 0xffffffff is ? According to the C standard, 6.4.4.1 Integer constants, the type of the expression of a hexadecimal constant (preceded with 0x) is the first of the following which can applicably hold the represented value:

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

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

On your platform, 0xFFFFFFFF cannot be represented as int because int is 32 bits and only 31 bits express quantity in signed int (the standard dictates one bit is reserved for sign). The next type, unsigned int, is therefore used. Therefore no sign bit is present to extended with the shift operation, which is thereby logical rather than arithmetic.

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

It may not be apparent how I concluded int was 32 bits on your platform. Indeed I could not make that assumption were it not for the first line, which arithmetic-right-shifts the value of -1. The result of that shift, dumped as %x, was 0xFFFFFFFF. Had int been native 64-bits that should dump 0xFFFFFFFFFFFFFFFF instead. Without that prior knowledge, no single type conclusion of 0xFFFFFFFF could be assumed since it may well be representable as a standard signed int of width 64-bits (63+1) with value 0x00000000FFFFFFFF. The resulting shift would produce the same output you see now, thereby introducing an alternative to that postulated above.

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

#2


6  

Your main question is: is 0xffffffff unsigned?

你的主要问题是:0xffffffff是无符号的吗?

From C11 §6.4.4.1 Integer constants

从C11§6.4.4.1整数常量

The type of an integer constant is the first of the corresponding list in which its value can be represented.

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

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

The output of your first printf line suggests that int is 32-bit on your machine. Thus it can not represent 0xffffffff, it must be unsigned.

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