为什么vector.size() -某些东西可以给分割错误?



在下面的代码中,for循环不会运行(由于条件i<0-1),并且不会打印任何内容:

#include <iostream>
#include <vector>
using namespace std;
int main() {
for(int i=0; i < 0-1; i++){
cout<<"Yes"<<endl;
}
return 0;
}

但是当我执行以下操作时,向量大小如预期的那样打印为0。所以for loop不应该打印任何东西,就像上面的情况一样。但事实上,这样的东西给我的错误,如分割故障或SIGKILL打印Yes多次后(在在线ide使用c++ 14 gcc 6.3):

#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> a;
cout<<a.size()<<endl;
for(int i=0;i<a.size()-1;i++){
cout<<"Yes"<<endl;
}
return 0;
}

我注意到的另一件事是它按预期工作如果我用a.size()代替a.size() - 1

a.size()返回一个无符号整数。当你从无符号0中减去1时,它会溢出(查找"unsigned integer underflow"到0xFFFFFFFF(一个非常大的数字)。所以你的循环运行了很长时间。

事实上,因为所有可能的ints都小于0xFFFFFFFF,编译器足够聪明,知道i<a.size()-1将永远不会为真,它只是把循环变成一个无限循环。

你可以在Godbolt上验证这种行为。

以下代码:

#include <vector>
using namespace std;
void foo() {
vector<int> a;
for(int i=0;i<a.size()-1;i++){
asm("");
}
}

被编译成这个程序集:

foo():                                # @foo()
.LBB0_1:                                # =>This Inner Loop Header: Depth=1
jmp     .LBB0_1

就是一个无限循环。asm("")是一种魔法,使编译器不会删除循环体。

1是一个类型为int的整型字量,但std::vector<int>::size()返回一个无符号值。

更好的比较是

#include <iostream>
#include <vector>
int main() {
for(int i=0; i < 0u -1; i++){
std::cout << "Yes" << std::endl;
}
}

0u是一个无符号整数字面值,而0u -1是一个非常大的数字。当您运行此代码时,您将看到与vector大小相同的效果。

一个变通方法是加而不是减:

#include <iostream>
#include <vector>
int main() {
std::vector<int> a;
std::cout << a.size() << std::endl;
for(int i=0; i+1 < a.size(); i++){
std::cout<< "Yes" << std::endl;
}
}

最新更新