简体   繁体   English

unsigned int /有符号int / long long:莫名其妙的输出

[英]unsigned int / signed int / long long: inexplicable output

So I was playing around with types and I came out with this weird result below. 所以我在玩各种类型,然后在下面得出了这个奇怪的结果。 Debugging it made no sense, and then the only result was to check out the c++ spects, which didn't helped much. 对其进行调试没有任何意义,然后唯一的结果就是检查c ++点,但并没有太大帮助。 I was wondering if you might know what is happening here exactly, and if it is 32Bit and/or 64Bit specific issue. 我想知道您是否确切知道这里发生了什么,是否是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;
}

Where the output is 输出在哪里

this is a weird 4294967295 -1

The key observation is that the expression -1 * u is of type unsigned int . 关键的观察结果是表达式-1 * u的类型为unsigned int That is because the rules for arithmetic conversions* say that if one operand is unsigned int and the other is signed int , then the latter operand is converted to unsigned int . 这是因为算术转换的规则*指出,如果一个操作数是unsigned int ,而另一个是有signed int ,则后一个操作数将转换unsigned int The arithmetic expressions are ultimately only defined for homogeneous operands, so the conversions happen before the operation proper. 算术表达式最终仅针对齐次操作数定义,因此转换发生在适当的运算之前。

The result of the conversion of -1 to unsigned int is a large, positive number, which is representable as a long long int , and which is the number you see in the output. -1unsigned int的转换结果是一个很大的正数,可以表示为long long int ,这是您在输出中看到的数字。

Currently, that's [expr]/(11.5.3). 当前是[expr] /(11.5.3)。

The evaluation of 评价

-1 * i

is trivial multiplication of two int types: nothing strange there. 是两个int类型的平凡乘法:那里没有什么奇怪的。 And a long long must be capable of holding any int . 并且很long long必须能够容纳任何int


First note is there is no such thing as a negative literal in C++, so 首先要注意的是,C ++中没有否定文字。

-1 * u

is evaluated as (-1) * u due to operator precedence. 由于运算符的优先级,其值为(-1) * u The type of (-1) must be int . (-1)的类型必须为int But this will be converted to unsigned int due to C++'s rule of argument conversion as the other argument is an unsigned int In doing that it is converted modulo UINT_MAX + 1 , so you end up with UINT_MAX multiplied by 1, which is the number you observe, albeit converted to a long long type. 但这将由于C ++的参数转换规则而被转换为unsigned int因为另一个参数是unsigned int 。这样做是对UINT_MAX + 1模转换,因此最终将UINT_MAX乘以1,这就是您观察到的数字,尽管已转换为long long类型。

As a final note, the behaviour of this conversion is subject to the rules of conversion from an unsigned to a signed type: if unsigned int and long long were both 64 bits on your platform then the behaviour is implementation-defined. 最后要注意,这个转换的行为是受到来自一个转换规则unsignedsigned类型:如果unsigned intlong long是你的平台上都为64位,则行为是实现定义的。

The type of -1 is signed int . -1的类型为有signed int When you perform an arithmetic operation between objects of different fundamental type, one or both of the arguments will be converted so that both have the same type. 当您在不同基本类型的对象之间执行算术运算时,将转换一个或两个参数,以使两者具有相同的类型。 (For non-fundamental types, there may be operator overloads for mixed operands). (对于非基本类型,混合操作数可能会有运算符重载)。 In this case, the signed value is converted to unsigned, following the conversion rules . 在这种情况下,将遵循转换规则将有符号值转换为无符号值。

So, -1 was converted to unsigned. 因此, -1被转换为无符号。 But negative numbers cannot be represented by unsigned types. 但是负数不能用无符号类型表示。 What happens, is that the resulting value will be the smallest positive value that can be represented by the unsigned type, that is congruent with the original signed value modulo the maximum value representable by unsigned type. 发生的结果是,结果值将是可以由无符号类型表示的最小正值,即与原始有符号值一致,而无符号类型可以表示的最大值与之相等。 Which on your platform happens to be 4294967295. 您平台上的哪个恰好是4294967295。


The rules ([expr], standard draft): 规则([expr],标准草案):

... rules that apply to non-integers ... 适用于非整数的规则

Otherwise, the integral promotions (4.5) shall be performed on both operands.61 Then the following rules shall be applied to the promoted operands: 否则,应在两个操作数上执行整数提升(4.5)。61然后,以下规则应应用于提升的操作数:

— If both operands have the same type, no further conversion is needed. —如果两个操作数具有相同的类型,则无需进一步转换。

— Otherwise, if both operands have signed integer types or both have unsigned integer types, the operand with the type of lesser integer conversion rank shall be converted to the type of the operand with greater rank. —否则,如果两个操作数都具有符号整数类型或都具有无符号整数类型,则应将具有较小整数转换等级的操作数转换为具有较大等级的操作数的类型。

— Otherwise, if the operand that has unsigned integer type has rank greater than or equal to the rank of the type of the other operand, the operand with signed integer type shall be converted to the type of the operand with unsigned integer type. —否则,如果具有无符号整数类型的操作数的秩大于或等于另一个操作数的类型的秩,则应将具有符号整数类型的操作数转换为具有无符号整数类型的操作数的类型。 (this applies to your case) (这适用于您的情况)

— Otherwise, if the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, the operand with unsigned integer type shall be converted to the type of the operand with signed integer type. —否则,如果带符号整数类型的操作数的类型可以表示无符号整数类型的操作数的所有值,则应将无符号整数类型的操作数转换为带符号整数类型的操作数的类型。

— Otherwise, both operands shall be converted to the unsigned integer type corresponding to the type of the operand with signed integer type. —否则,两个操作数均应转换为与带符号整数类型的操作数类型相对应的无符号整数类型。

The bit pattern "0xFFFFFFFF" corresponds with "-1" when interpreted as a 32b signed integer and corresponds with "4294967295" when interpreted as a 32b unsigned integer. 位模式“ 0xFFFFFFFF”在解释为32b有符号整数时与“ -1”相对应,在解释为32b无符号整数时与“ 4294967295”相对应。

  • If used -2 the result is "4294967294" 如果使用-2,则结果为“ 4294967294”
  • If used -3 the result is "4294967293" 如果使用-3,则结果为“ 4294967293”
  • If used -4 the result is "4294967292" 如果使用-4,则结果为“ 4294967292”
  • .... ....

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM