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

时间:2017-01-18 13:17:26

标签: c++

所以我正在玩各种类型,我在下面提出了这个奇怪的结果。调试它没有任何意义,然后唯一的结果是检查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

4 个答案:

答案 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 longunsigned类型转换规则的约束:如果signedunsigned 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无符号整数时。

  • 如果使用-2,结果为&#34; 4294967294&#34;
  • 如果使用-3,则结果为&#34; 4294967293&#34;
  • 如果使用-4,则结果为&#34; 4294967292&#34;
  • ....