如果我将负值赋给无符号变量会发生什么?

问题描述 投票:0回答:7

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

代码看起来有点像这样。

unsigned int nVal = 0;
nVal = -5;

它没有给我任何编译器错误。当我运行程序时,

nVal
被分配了一个奇怪的值!是否有可能某个 2 的补码值被分配给
nVal

c++ type-conversion integer unsigned signed
7个回答
79
投票

官方答案 - 第 4.7 节 conv.integral

“如果目标类型是无符号的,则结果值是与源整数一致的最小无符号整数(模 2n,其中

n
是用于表示无符号类型的位数)。[注:In二进制补码表示,这种转换是概念性的,位模式没有变化(如果没有截断)。—尾注]

这本质上意味着,如果底层架构存储在不是补码的方法中(例如有符号数或补码),则到无符号的转换必须表现得就像是补码一样。

(C++20 及更高版本要求有符号整数使用 2 的补码,但早期版本的标准允许使用其他表示形式。)

“...全等...”部分意味着您添加或减去 2n 直到该值位于无符号类型的值范围内。对于 2 的补码,这意味着进行 2 的补码符号扩展或截断。对于相同的宽度,位模式不变,因为添加 2n 是无操作:2

n
的低 n 位全部为零。 2 的补码加法/减法与无符号的按位运算相同,这就是它的特殊之处。


46
投票

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


5
投票

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


4
投票

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

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


2
投票

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


2
投票

当您为无符号变量分配负值时,它会使用 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

0
投票

在 Windows 和 Ubuntu Linux 中,我检查过将任何负数(不仅仅是

-1
)分配给 C 和 C++ 中的无符号整数都会导致将值
UINT_MAX
分配给该无符号整数。

编译示例链接.

© www.soinside.com 2019 - 2024. All rights reserved.