所以我正在玩各种类型,我在下面提出了这个奇怪的结果。调试它没有任何意义,然后唯一的结果是检查c ++ spects,这没有多大帮助。我想知道你是否可能知道这里发生了什么,如果它是32Bit和/或64Bit特定问题。
#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
答案 0 :(得分:5)
关键观察结果是-1 * u
表达式为unsigned int
类型。这是因为算术转换的规则*表示如果一个操作数是unsigned int
而另一个是signed int
,则后一个操作数被转换到unsigned int
。算术表达式最终只针对同构操作数定义,因此转换发生在正确的操作之前。
将-1
转换为unsigned int
的结果是一个较大的正数,可以表示为long long int
,这是您在输出中看到的数字。 / p>
目前,那是[expr] /(11.5.3)。
答案 1 :(得分:1)
评估
-1 * i
是两种int
类型的琐碎乘法:没有什么奇怪的。并且long long
必须能够保留任何int
。
首先要注意的是C ++中没有负面文字,所以
-1 * u
被评估为(-1) * u
。 (-1)
的类型必须为int
。但是由于C ++的参数规则转换,这将转换为unsigned int
,因为另一个参数是unsigned int
在这样做时,它以模UINT_MAX + 1
为模转换,因此最终得到{{1}乘以1,这是你观察到的数字,虽然转换为UINT_MAX
类型。
最后请注意,此转化的行为受long long
到unsigned
类型转换规则的约束:如果signed
和unsigned int
都是在您的平台上64位,然后行为是实现定义。
答案 2 :(得分:1)
-1
的类型为signed int
。当您在不同基本类型的对象之间执行算术运算时,将转换一个或两个参数,以便两者具有相同的类型。 (对于非基本类型,混合操作数可能存在运算符重载)。在这种情况下,符合转换规则†后,有符号值将转换为无符号值。
因此,-1
已转换为无符号。但负数不能用无符号类型表示。所发生的是,结果值将是可以由无符号类型表示的最小正值,其与原始有符号值一致,以无符号类型表示的最大值为模。您的平台上恰好是4294967295。
†规则([expr],标准草案):
...适用于非整数的规则......
否则,应对两个操作数执行整数提升(4.5).61然后执行以下操作 规则应适用于推广的操作数:
- 如果两个操作数具有相同的类型,则不需要进一步转换。
- 否则,如果两个操作数都有有符号整数类型或两者都有无符号整数类型,则 具有较小整数转换等级类型的操作数应转换为类型 操作数更高的等级。
- 否则,如果具有无符号整数类型的操作数的等级大于或等于 另一个操作数的类型的等级,带有符号整数类型的操作数应转换为 具有无符号整数类型的操作数的类型。 (这适用于您的情况)
- 否则,如果带有符号整数类型的操作数的类型可以表示的所有值 具有无符号整数类型的操作数的类型,具有无符号整数类型的操作数应为 转换为带有符号整数类型的操作数的类型。
- 否则,两个操作数都应转换为对应的无符号整数类型 带有符号整数类型的操作数的类型。
答案 3 :(得分:0)
位模式&#34; 0xFFFFFFFF&#34;对应于&#34; -1&#34;当被解释为32b有符号整数并且对应于&#34; 4294967295&#34;当解释为32b无符号整数时。