【问题标题】:unsigned(0) - 1 generates "segment fault"unsigned(0) - 1 生成“段错误”
【发布时间】:2017-03-23 04:06:18
【问题描述】:

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

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

【问题讨论】:

    标签: types type-conversion


    【解决方案1】:

    这是因为 size 是无符号的。如果从无符号数中减去 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 变为全 1)。这是因为通常情况下,负数以一种称为二进制补码的形式表示 - 要使一个数为负数,您需要翻转该数的所有位,并将结果加 1。

    对于负数(示例为 4 位):

    0001 = 4
    1110 = flipped
    1111 = flipped + 1
    

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

    因此,从 0000 中减去 1 应该得到 1111。

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

    这一切都很好,但这意味着您可以使用更少的位来存储 LARGE 数字。

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

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

    同样,如果你有一个 32 位整数设置为可以用 32 位表示的最大可能数(假设无符号),并在其上加 1,该数将回绕,回到 0。

    这些问题称为上溢和下溢。

    【讨论】:

    • 是的,谢谢。我已经在我的电脑上试过了。但是,当(unsinged int)0-1 时,我不清楚幕后发生了什么。你能在这里澄清一下吗?非常感谢
    • 我修改了我的答案,以便在“更多关于无符号数字”的文本下对此进行更多解释。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-11
    • 2014-12-20
    相关资源
    最近更新 更多