如果我将负值赋给无符号变量会发生什么?
我很想知道如果我为无符号变量分配负值会发生什么。
代码看起来有点像这样。
unsigned int nVal = 0;
nVal = -5;
它没有给我任何编译器错误。当我运行程序时,nVal
被分配了一个奇怪的值!是否有可能某个 2 的补码值被分配给了 nVal?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
官方答案 - 第 4.7 节 conv.integral 用于从签名转换整数类型。
这本质上意味着如果底层架构存储在不是补码的方法中(例如有符号数或补码),因此到无符号的转换必须像补码一样进行
(C++20 及更高版本要求有符号整数使用 2 的补码 。 ,但标准的早期版本允许这些其他表示。)
“...全等...”部分意味着您添加或减去 2n 直到该值位于对于无符号类型,这意味着进行 2 的补码符号扩展或截断。对于相同的宽度,位模式不变,因为添加 2n 是无操作:低位
n 中的 >n 位均为零。 2 的补码加法/减法与无符号的按位运算相同,这就是它的特殊之处。
附言。从浮点到无符号的转换工作方式不同:如果值超出无符号类型的范围(如果截断为整数后为负或太大),则这是未定义的行为。模数减少仅发生在有符号整数到无符号整数的情况下。
For the official answer - Section 4.7 conv.integral for conversion from signed integral types.
This essentially means that if the underlying architecture stores in a method that is not Two's Complement (like Signed Magnitude, or One's Complement), that the conversion to unsigned must behave as if it was Two's Complement.
(C++20 and later require that signed integers use 2's complement, but earlier versions of the standard allowed those other representations.)
The "... congruent ..." part means that you add or subtract 2n until the value is in the value-range of the unsigned type. For 2's complement, this means doing 2's complement sign-extension or truncation. For the same width, the bit-pattern is unchanged because adding 2n is a no-op: the low
n
bits of 2n are all zero. 2's complement addition/subtraction are the same bitwise operation as unsigned, which is what makes it special.PS. conversion from floating point to unsigned works differently: it's undefined behavior if the value is out of range for the unsigned type (if it's negative after truncation to integer or too large). Modulo reduction only happens for signed integer to unsigned integer.
它将代表 -5(2 的补码)的位模式分配给 unsigned int。这将是一个很大的无符号值。对于 32 位整数,这将是 2^32 - 5 或 4294967291
It will assign the bit pattern representing -5 (in 2's complement) to the unsigned int. Which will be a large unsigned value. For 32 bit ints this will be 2^32 - 5 or 4294967291
你是对的,有符号整数以2的补码形式存储,无符号整数存储在 无符号二进制表示。 C(和 C++)不区分两者,因此最终得到的值只是 2 的补码二进制表示形式的无符号二进制值。
You're right, the signed integer is stored in 2's complement form, and the unsigned integer is stored in the unsigned binary representation. C (and C++) doesn't distinguish between the two, so the value you end up with is simply the unsigned binary value of the 2's complement binary representation.
它将显示为最大无符号整数 - 4 的正整数值(值取决于计算机体系结构和编译器)。
顺便说一句
您可以通过编写一个简单的 C++“hello world”类型程序来检查这一点,并亲自查看
It will show as a positive integer of value of max unsigned integer - 4 (value depends on computer architecture and compiler).
BTW
You can check this by writing a simple C++ "hello world" type program and see for yourself
当您将负值分配给无符号变量时,它会使用 2 的补码方法来处理它,在该方法中,它将所有 0 翻转为 1,将所有 1 翻转为 0,然后将其加 1。在您的情况下,您正在处理 4 字节(32 位)的 int,因此它尝试对 32 位数字使用 2 的补码方法,这会导致较高位翻转。例如:
When you assign a negative value to an unsigned variable then it uses the 2's complement method to process it and in this method it flips all 0s to 1s and all 1s to 0s and then adds 1 to it. In your case, you are dealing with int which is of 4 byte(32 bits) so it tries to use 2's complement method on 32 bit number which causes the higher bit to flip. For example:
是的,你是对的。分配的实际值类似于除第三位之外的所有位设置。 -1 是设置的所有位(十六进制:0xFFFFFFFF),-2 是除第一个之外的所有位,依此类推。您将看到的可能是十六进制值 0xFFFFFFFB,其十进制对应于 4294967291。
Yes, you're correct. The actual value assigned is something like all bits set except the third. -1 is all bits set (hex: 0xFFFFFFFF), -2 is all bits except the first and so on. What you would see is probably the hex value 0xFFFFFFFB which in decimal corresponds to 4294967291.
在 Windows 和 Ubuntu Linux 中,我检查过将任何负数(不仅仅是
-1
)分配给 C 和 C++ 中的无符号整数都会导致将值UINT_MAX
分配给那个无符号整数。编译示例链接。
In Windows and Ubuntu Linux that I have checked assigning any negative number (not just
-1
) to an unsigned integer in C and C++ results in the assignment of the valueUINT_MAX
to that unsigned integer.Compiled example link.