C++ 如果我给一个无符号变量赋值为负值会发生什么?

C++ 如果我给一个无符号变量赋值为负值会发生什么?,c++,type-conversion,integer,unsigned,signed,C++,Type Conversion,Integer,Unsigned,Signed,我很想知道如果我给一个无符号变量赋值,会发生什么 代码看起来有点像这样 unsigned int nVal = 0; nVal = -5; 它没有给我任何编译器错误。当我运行程序时,nVal被分配了一个奇怪的值!是否有一些2的补码值被分配给nVal?它将显示为最大无符号整数-4值的正整数(该值取决于计算机体系结构和编译器) 顺便说一句 您可以通过编写一个简单的C++“Hello World”类型程序来检查这个问题,并且亲自查看< /P> < P>是的,您是正确的。分配的实际值类似于除第三位之外

我很想知道如果我给一个无符号变量赋值,会发生什么

代码看起来有点像这样

unsigned int nVal = 0;
nVal = -5;

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

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

顺便说一句

您可以通过编写一个简单的C++“Hello World”类型程序来检查这个问题,并且亲自查看< /P> < P>是的,您是正确的。分配的实际值类似于除第三位之外的所有位集-1是设置的所有位(十六进制:0xFFFFFF),-2是除第一位以外的所有位,依此类推。您可能会看到十六进制值0xFFFFFB,十进制对应于4294967291。

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

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

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


这本质上意味着,如果底层架构存储的方法不是2的补码(如有符号的幅值或1的补码),表示转换为无符号必须表现为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

我写了这个问题并检查了它,这就是为什么我问这个问题,但我不知道编译器是如何达到这个值的。幸亏有C++,编写程序来测试行为并不总是一个好主意。例如,如果尝试测试在签名溢出的情况下发生什么,它会导致未定义的行为,这是不保证的。我的直觉(还没在标准中找到它)行为在技术上是未定义的。此外,我怀疑你会在几乎所有你能找到的编译器上看到你所期望的。因此,虽然你通常会看到这种行为,但依靠它可能不是一个好主意。它不是未定义的(见§4.7/2),但表示(例如2s补码)不是标准强制要求的。@gf(下面等),酷。看起来行为实际上是明确定义为您所期望的,@viswanathan。第二行相当于
nVal=(unsigned int)-5;
。将
-5
转换为
无符号int
在6.3.1.3中有定义。标准不强制要求使用2s补码表示,但转换为无符号int的算法是:这个值是通过重复添加或减去一个比在NeXType中可以表示的最大值多一倍的值来转换的,直到值在NeXType的范围内。“@ Pascal:你似乎指的是C99,但问题是标记C++。它可能不被存储在2的恭维中。如果某物被存储在2的中,这意味着什么?”" @GManNickG@JeremyF:不是“2的”、“2的赞美”。这是一个谷歌术语,是一种表示有符号整数的方式。比特与之无关。@BenVoigt:很公平,我的意思是它与比特的解释方式无关。(也就是说,引用部分中的“比特”只是
ceil(log_2(x))
)@gmanickg比特的缩写(比如,属于比特)?2的赞美?嘎嘎!NullUserException:哈哈,我知道。用“*”代替“*s”是我一段时间以来的一个可怕习惯。至于赞美而不是补语,那纯粹是愚蠢的行为。:)简单是关键。这个答案就是。(2^32-5)比引用文档更好地解释这种行为。位与此无关,未指定整数表示法。您的答案正确、严格,而且是我在课堂上永远不会使用的。请参阅我的答案,了解2的-5补码。我认为您对二进制值的计算不正确。这是什么与源整数均值一致的最小无符号整数?例如,DavIDRODR Guez DunBeas,5和3是“一致MOD 2”,因为5%个2和3%个2都是1。