当foo.size()为0时,为什么下面的代码会生成“段错误”?这是因为类型转换吗?
int main()
{
vector <int> foo;
for (int i = 0; i < foo.size() - 1; i++) {
cout << foo[i] << endl;
}
return 0;
}
答案 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。
这些问题被称为溢出和下溢。