我很想知道如果我给一个无符号变量分配一个负值会发生什么。
代码看起来有点像这样。
unsigned int nVal = 0;
nVal = -5;
它没有给我任何编译器错误。当我运行程序时,它nVal
被分配了一个奇怪的值!会不会是一些 2 的补码被分配给nVal
?
我很想知道如果我给一个无符号变量分配一个负值会发生什么。
代码看起来有点像这样。
unsigned int nVal = 0;
nVal = -5;
它没有给我任何编译器错误。当我运行程序时,它nVal
被分配了一个奇怪的值!会不会是一些 2 的补码被分配给nVal
?
对于官方答案 - 第 4.7 节conv.integral
“如果目标类型是无符号的,则结果值是与源整数一致的最小无符号整数(模 2 n其中
n
是用于表示无符号类型的位数)。[注意:在二进制补码表示中,此转换是概念性的,位模式没有变化(如果没有截断)。-尾注]
这实质上意味着,如果底层架构存储在一个不是二进制补码的方法中(如有符号幅度或 One 的补码),则到无符号的转换必须表现得好像它是二进制补码一样。
它将表示 -5(2 的补码)的位模式分配给 unsigned int。这将是一个很大的无符号值。对于 32 位整数,这将是 2^32 - 5 或 4294967291
没错,有符号整数以 2 的补码形式存储,无符号整数以无符号二进制表示形式存储。C(和 C++)不区分两者,所以你最终得到的值只是 2 的补码二进制表示的无符号二进制值。
它将显示为最大无符号整数值的正整数 - 4(值取决于计算机体系结构和编译器)。
顺便说一句
,您可以通过编写一个简单的 C++“hello world”类型程序来检查这一点,然后自己看看
是的,你是对的。分配的实际值类似于除第三位之外的所有位设置。-1 是所有位设置(十六进制:0xFFFFFFFF),-2 是除第一个以外的所有位,依此类推。你看到的可能是十六进制值 0xFFFFFFFB,十进制对应 4294967291。
当您为无符号变量分配负值时,它会使用 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