unsigned int/signed int/long-long:无法解释的输出



所以我一直在玩类型,我得到了下面这个奇怪的结果。对它进行调试毫无意义,然后唯一的结果就是检查了c++的检查,这并没有多大帮助。我想知道你是否知道这里到底发生了什么,以及它是否是32位和/或64位特定的问题。

#include <iostream>
using namespace std;
int main() {
unsigned int u = 1;
signed int i = 1;
long long lu = -1 * u;
long long li = -1 * i;
std::cout<<"this is a weird " << lu << " " << li << std::endl;
return 0;
}

输出为

this is a weird 4294967295 -1

关键的观察结果是表达式-1 * u的类型为unsigned int。这是因为算术转换的规则*说,如果一个操作数是unsigned int,另一个是signed int,则后一个操作数转换为unsigned int。算术表达式最终只为同构操作数定义,因此转换发生在操作正确之前。

-1转换为unsigned int的结果是一个大的正数,它可以表示为long long int,也是您在输出中看到的数字。

目前,这是[Epr]/(11.5.3)。

-1的类型为signed int。当您在不同基本类型的对象之间执行算术运算时,其中一个或两个参数将被转换,以便两者具有相同的类型。(对于非基本类型,混合操作数可能存在运算符重载)。在这种情况下,有符号值被转换为无符号值,遵循转换规则

因此,-1被转换为无符号。但是负数不能用无符号类型表示。结果是,得到的值将是无符号类型可以表示的最小正值,与原始有符号值一致,取无符号类型可表示的最大值的模。在您的平台上,恰好是4294967295。


规则([expr],标准草案):

。。。适用于非整数的规则。。。

否则,应在两个操作上执行整体提升(4.5)。61然后执行以下操作规则应适用于提升的操作数:

--如果两个操作数都具有相同的类型,则不需要进一步的转换。

--否则,如果两个操作数都具有有符号整数类型或都具有无符号整数类型,则具有较小整数转换秩类型的操作数应转换为秩较大的操作数。

--否则,如果具有无符号整数类型的操作数的秩大于或等于另一个操作数类型的秩,带符号整数类型的操作数应转换为具有无符号整数类型的操作数的类型(这适用于您的情况)

--否则,如果带符号整数类型的操作数的类型可以表示具有无符号整数类型的操作数的类型,具有无符号整型的操作数应转换为带符号整数类型的操作数的类型。

--否则,两个操作数都应转换为与带符号整数类型的操作数的类型。

的评估

-1 * i

是两个int类型的平凡乘积:没有什么奇怪的。并且long long必须能够容纳任何int


首先要注意的是,C++中没有负文字,所以

-1 * u

由于运算符优先级的原因被评估为CCD_ 17。(-1)的类型必须是int。但是,由于C++的参数转换规则,这将被转换为unsigned int,因为另一个参数是unsigned int。在这样做的过程中,它被转换为模UINT_MAX + 1,所以你最终得到的是UINT_MAX乘以1,这是你观察到的数字,尽管转换为了long long类型。

最后要注意的是,这种转换的行为受从unsignedsigned类型的转换规则的约束:如果unsigned intlong long在您的平台上都是64位,那么行为就是实现定义的。

当被解释为32b有符号整数时,位模式"0xFFFFFFFF"对应于"-1",当被理解为32b无符号整数时对应于"4294967295"。

  • 如果使用-2,结果为"4294967294">
  • 如果使用-3,则结果为"4294967293">
  • 如果使用-4,则结果为"4294967292">

最新更新