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

发布于 2024-08-30 05:34:23 字数 195 浏览 6 评论 0 原文

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

代码看起来有点像这样。

unsigned int nVal = 0;
nVal = -5;

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

I was curious to know what would happen if I assign a negative value to an unsigned variable.

The code will look somewhat like this.

unsigned int nVal = 0;
nVal = -5;

It didn't give me any compiler error. When I ran the program the nVal was assigned a strange value! Could it be that some 2's complement value gets assigned to nVal?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

我们的影子 2024-09-06 05:34:23

官方答案 - 第 4.7 节 conv.integral 用于从签名转换整数类型。

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

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

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

“...全等...”部分意味着您添加或减去 2n 直到该值位于对于无符号类型,这意味着进行 2 的补码符号扩展或截断。对于相同的宽度,位模式不变,因为添加 2n 是无操作:低位 n 中的 >n 位均为零。 2 的补码加法/减法与无符号的按位运算相同,这就是它的特殊之处。


附言。从浮点到无符号的转换工作方式不同:如果值超出无符号类型的范围(如果截断为整数后为负或太大),则这是未定义的行为。模数减少仅发生在有符号整数到无符号整数的情况下。

For the official answer - Section 4.7 conv.integral for conversion from signed integral types.

"If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source integer (modulo 2n where n is the number of bits used to represent the unsigned type). [ Note: In a two’s complement representation, this conversion is conceptual and there is no change in the bit pattern (if there is no truncation). —end note ]

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.

终难遇 2024-09-06 05:34:23

它将代表 -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

黯淡〆 2024-09-06 05:34:23

你是对的,有符号整数以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.

无声无音无过去 2024-09-06 05:34:23

它将显示为最大无符号整数 - 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

残疾 2024-09-06 05:34:23

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

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:

┌─[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
决绝 2024-09-06 05:34:23

是的,你是对的。分配的实际值类似于除第三位之外的所有位设置。 -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.

对风讲故事 2024-09-06 05:34:23

在 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 value UINT_MAX to that unsigned integer.

Compiled example link.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文