Possible Duplicate:
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
。所以我想了解内存中发生了什么?在这个计算继续进行的同时,正在进行什么样的过程?感谢您的回答。
您遇到了环绕行为。
无符号类型是循环的(另一方面,有符号类型可能是也可能不是循环的,但它是您不应该依赖的未定义行为)。也就是说,比最小可能值小1就是最大可能值。您可以使用以下代码段自行演示:
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 字节)更有意义像这样,因为如果转换为 unsigned char
,值 0 和 256 是相等的,因为有限的精度会丢弃额外的位。
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 的模,则该值将与您完全相同已将其转换为无符号整数。
01011010 01011100 10000001 00001101 11111111 11111111 11111111 11111111 // before
00000000 00000000 00000000 00000000 11111111 11111111 11111111 11111111 // after
程序员喜欢使用此属性来加快程序速度,因为它很容易砍掉一些位数,但执行模运算要困难得多(与除法一样难)。
这有意义吗?