无符号整数背后的想法

时间:2012-10-08 17:28:58

标签: c++ unsigned-integer

  

可能重复:
  What happens if I assign a negative value to an unsigned variable?

我是C ++的新手,我想知道如何使用无符号类型。对于unsigned int类型,我知道它可以取0到4294967296之间的值。但是当我想初始化unsigned int类型时,如下所示:

unsigned int x = -10;
cout << x;

输出似乎是4294967286 得到了这个output = max value - 10。所以我想了解记忆中发生的事情?在计算继续进行的过程中,正在进行哪些处理?谢谢你的回答。

3 个答案:

答案 0 :(得分:6)

你正在遇到环绕行为。

无符号类型是循环的(另一方面,有符号类型可能是循环的,也可能不是循环的,但它是您不应该依赖的未定义行为)。也就是说,小于最小可能值的是最大可能值。您可以使用以下代码段自行演示:

int main()
{
    unsigned int x = 5;
    for (int i = 0; i < 10; ++i) cout << x-- << endl;
    return 0;
}

你会注意到,在达到零之后,x的值跳转到2 ^ 32-1,即最大可表示值。按预期减去进一步的行为。

从无符号0中减1时,位模式按以下方式更改:

0000 0000 0000 0000 0000 0000 0000 0000 // before (0)
1111 1111 1111 1111 1111 1111 1111 1111 // after  (2^32 - 1)

对于无符号数,负数被视为从零中减去的正数。因此(unsigned int) -10将等于((unsigned int) 0) - ((unsigned int) 10)

我喜欢把它看作无符号整数,它是高精度任意值的最低32位。像这样:

v imaginary high order bit
1 0000 0000 0000 0000 0000 0000 0000 0000 // before (2^32)
0 1111 1111 1111 1111 1111 1111 1111 1111 // after  (2^32 - 1)

在这些溢出情况下unsigned int的行为与从256中减去1时unsigned int的低8位的行为完全相同。查看unsigned char(1字节)更有意义像这样,因为值0和256相等,如果转换为unsigned char,因为有限的精度会丢弃额外的位。

0 0000 0000 0000 0000 0000 0001 0000 0000 // before (256)
0 0000 0000 0000 0000 0000 0000 1111 1111 // before (255)

正如其他人所指出的,这被称为模运算。使用更高精度的值来帮助可视化环绕工作时的转换,因为您屏蔽了高阶位。无论它是什么,所以它可以是任何东西,它只是被丢弃。整数是超过模数2 ^ 32的值,因此任何2 ^ 32的倍数在整数的空间中等于零。这就是为什么我可以假装最后还有一点额外的东西。

模数运算有自己的专用运算符,以防您需要在程序中为2 ^ 32以外的数字计算它们,如本声明中所使用的那样:

int forty_mod_twelve = 40 % 12;
// value is 4: 4 + n * 12 == 40 for some whole number n

对2的幂的模运算(如2 ^ 32)直接简化为屏蔽高阶位,如果你取64位整数并计算模2 ^ 32,则该值将与您完全相同已将其转换为unsigned int。

01011010 01011100 10000001 00001101 11111111 11111111 11111111 11111111 // before
00000000 00000000 00000000 00000000 11111111 11111111 11111111 11111111 // after

程序员喜欢使用这个属性来加速程序,因为它很容易切掉一些位,但是执行模数运算要困难得多(它和分割一样困难)。

这有意义吗?

答案 1 :(得分:4)

这涉及标准的积分转换。这是适用的规则。我们从文字10

的类型开始
  

2.14.2整数文字[lex.icon]

     

整数文字是一系列没有句点或指数部分的数字。整数文字可能有   一个指定其基数的前缀和一个指定其类型的后缀。序列的词汇第一个数字   数字是最重要的。十进制整数文字(十进制)以0和以外的数字开头   由一系列十进制数字组成。八进制整数文字(基数为8)以数字0和。开头   由一系列八进制数字组成。十六进制整数文字(基数为16)以0x0X开头   由一系列十六进制数字组成,包括十进制数字和字母afAF,十进制值为十到十五。 [例如:数字12可以写为120140XC。 - 结束例子]

     

整数文字的类型是表6中相应列表的第一个,其值可以是   表示。

下面是一个表格,第一个类型是int,它适合。所以文字的类型是int

应用一元减号运算符,不会更改类型。然后应用以下规则:

  

4.7积分转换[conv.integral]

     

整数类型的prvalue可以转换为另一个整数类型的prvalue。可以将未范围的枚举类型的prvalue转换为整数类型的prvalue。

     

如果目标类型是无符号的,则结果值是与源整数一致的最小无符号整数(模2 n ,其中n是用于表示无符号类型的位数)。 [注意:在二进制补码表示中,此转换是概念性的,并且位模式没有变化(如果没有截断)。 - 结束说明]

答案 2 :(得分:0)

不是按照你的方式打印值,而是以十六进制格式打印(抱歉,我忘记了如何使用cout但我知道这是可能的)。您将看到两个值的表示相同。

从您的上下文中,整数是32位(情况并非总是如此)。使用有符号整数时,最高有效位是符号,而不是值的一部分。使用无符号整数时,最高有效位是值的一部分。