88

我很想知道如果我给一个无符号变量分配一个负值会发生什么。

代码看起来有点像这样。

unsigned int nVal = 0;
nVal = -5;

它没有给我任何编译器错误。当我运行程序时,它nVal被分配了一个奇怪的值!会不会是一些 2 的补码被分配给nVal

4

6 回答 6

74

对于官方答案 - 第 4.7 节conv.integral

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

这实质上意味着,如果底层架构存储在一个不是二进制补码的方法中(如有符号幅度或 One 的补码),则到无符号的转换必须表现得好像它是二进制补码一样。

于 2010-04-26T06:53:36.563 回答
40

它将表示 -5(2 的补码)的位模式分配给 unsigned int。这将是一个很大的无符号值。对于 32 位整数,这将是 2^32 - 5 或 4294967291

于 2010-04-26T06:51:55.943 回答
5

没错,有符号整数以 2 的补码形式存储,无符号整数以无符号二进制表示形式存储。C(和 C++)不区分两者,所以你最终得到的值只是 2 的补码二进制表示的无符号二进制值。

于 2010-04-26T06:49:02.913 回答
4

它将显示为最大无符号整数值的正整数 - 4(值取决于计算机体系结构和编译器)。

顺便说一句
,您可以通过编写一个简单的 C++“hello world”类型程序来检查这一点,然后自己看看

于 2010-04-26T06:46:50.783 回答
2

是的,你是对的。分配的实际值类似于除第三位之外的所有位设置。-1 是所有位设置(十六进制:0xFFFFFFFF),-2 是除第一个以外的所有位,依此类推。你看到的可能是十六进制值 0xFFFFFFFB,十进制对应 4294967291。

于 2010-04-26T06:48:16.387 回答
1

当您为无符号变量分配负值时,它会使用 2 的补码方法对其进行处理,并在此方法中将所有 0 翻转为 1,将所有 1 翻转为 0,然后将其加 1。在您的情况下,您正在处理 4 字节(32 位)的 int,因此它尝试对 32 位数字使用 2 的补码方法,这会导致较高位翻转。例如:

┌─[student@pc]─[~]
└──╼ $pcalc 0y00000000000000000000000000000101      # 5 in binary
        5                       0x5                     0y101
┌─[student@pc]─[~]
└──╼ $pcalc 0y11111111111111111111111111111010      # flip all bits  
      4294967290      0xfffffffa      0y11111111111111111111111111111010
┌─[student@pc]─[~]
└──╼ $pcalc 0y11111111111111111111111111111010 + 1  # add 1 to that flipped binarry
      4294967291      0xfffffffb      0y11111111111111111111111111111011
于 2020-04-27T10:06:12.400 回答