unsigned(0) - 1生成“段错误”

时间:2017-03-23 04:06:18

标签: types type-conversion

当foo.size()为0时,为什么下面的代码会生成“段错误”?这是因为类型转换吗?

 int main()
 {
   vector <int> foo;
   for (int i = 0; i < foo.size() - 1; i++) {
       cout << foo[i] << endl;
   }
   return 0;
}

1 个答案:

答案 0 :(得分:1)

这是因为尺寸未签名。如果从无符号数中减去0,则会得到该数字的最大值。尝试:

if(foo.size() > 0)
{
  for(int i = 0; i < foo.size() - 1; i++)
  {
    cout << foo[i] << endl;
  }
}

或者,更简单的解决方案,只是避免减去。改为添加。

for(int i = 0; i + 1 < foo.size(); i++)
{
  cout << foo[i] << endl;
}

如果在foo有0个元素时打印出foo.size() - 1,您可以确切地知道代码中发生了什么。在我的结尾,它打印18446744073709551615.这是一个非常大的非负数。

有关无符号数字的更多信息

当您从无符号(0)中减去1时,您的数字位都会变为1(它们从所有0&#39;到所有1&#39; s)。这是因为通常情况下,负数以称为“二进制补码”的形式表示 - 要使数字为负数,请翻转数字的所有位,然后将1加到结果中。

对于否定的一个(例子将是4位):

0001 = 4
1110 = flipped
1111 = flipped + 1

因此,在四位二进制补码中,-1表示为全1。

因此,从0000减去1会给你1111。

但计算机如何知道数字是否为负数? 简单。它假设最左边的位设置的任何数字都是负数。

这一切都很好,但这意味着可以使用少一点来存储大量数字。

如果您使用最高有效位来表示8位数字的数字符号,则可以表示的最大数字从255减少到127.

出于这个原因,我们偶尔会将数字视为无符号数,以便我们可以存储大值。缺点是如果我们从0中减去任何东西,我们将得到一个通常表示负数的结果,但将其解释为一个非常大的正数。

类似地,如果你有一个32位整数设置为可以用32位表示的最大可能数(假设是无符号),并且向它加1,则数字将回绕,返回0。

这些问题被称为溢出和下溢。