C++ 代码在 for 循环的条件下给出 运行-time 错误,而如果它被具有相同意义的代码替换,则编译正确

C++ code is giving a run-time error in the condition of for loop Whereas it is compiling correctly if it is replaced by code which makes same sense

#include<bits/stdc++.h>
using namespace std;

int main() {
vector<int> luck;
int k = 10;
int sum = 0;
for(int  i = 0; i<5; i++) luck.push_back(i);

for(int i = 0; i<luck.size() - k; i++) sum+=luck[i]; //RUNTIME ERROR

cout<<endl<<sum;
return 0;
}

wheareas 如果我添加

它会给出正确的输出
int boundary = luck.size() - k;

并将第二个'for'循环的条件替换为

i<boundary;

这里是完整无误的代码,再次:

#include<bits/stdc++.h>
using namespace std;
int main() {
vector<int> luck;
int k = 10;
int sum = 0;
for(int  i = 0; i<5; i++) luck.push_back(i);

int boundary = luck.size() - k;   // HERE 
for(int i = 0; i<boundary; i++) sum+=luck[i]; //CONDITION CHANGE

cout<<endl<<sum;
return 0;
}

您在 for 循环中混用了无符号和有符号。使代码工作的另一种方法是更改​​:

for(int i = 0; i<luck.size() - k; i++) sum+=luck[i]; //RUNTIME ERROR

至:

for(int i = 0; i < int(luck.size() - k); i++) sum+=luck[i];

解释:

luck.size() returns 无符号整数值 (std::vector::size_type)。当您从中减去 k 时,它仍被视为无符号整数。因为在你的情况下 k > luck.size(),结果是否定的。当你给无符号整数赋负值时,你会得到一个巨大的正数,所以循环不会正确停止。

在第二种情况下,赋值(对有符号整数)将 rhs 表达式视为有符号且代码按预期工作。

正如 DeiDei 所说,这是有符号和无符号整数不幸混合的结果。

请注意,std::vector::size() returns size_t

取决于平台,这通常是 32 位或 64 位 unsigned。 (size_t 的位数与 void* 相同。)

在第一个示例中:

for(int i = 0; i<luck.size() - k; i++) sum+=luck[i]; //RUNTIME ERROR

出现以下值:

luck.size(): (size_t)5

k: (int)10

luck.size() - k: (size_t)0xFFFFFFFFFFFFFFFFB(假设 64 位大小)

i < luck.size() - k的比较也将i提升为size_t。因此,迭代不会在 5 处停止。因此,在第一个示例代码中,您在循环中获得了越界访问。

在第二个样本中:

int boundary = luck.size() - k;   // HERE 
for(int i = 0; i<boundary; i++) sum+=luck[i]; //CONDITION CHANGE

该值再次转换为 int

int boundary = luck.size() - k;: (int)-5

这导致没有循环迭代。

演示:

#include <iostream>
#include <vector>

int main()
{
  std::vector<int> luck;
  int k = 10;
  int sum = 0;
  for(int  i = 0; i<5; i++) luck.push_back(i);
  // trying 2nd version:
  std::cout << "2nd version:\n";
  int boundary = luck.size() - k;   // HERE 
  for(int i = 0; i<boundary; i++) {
    std::cout << "i: " << i << '\n';
    sum+=luck[i]; //CONDITION CHANGE
  }
  std::cout << "sum: " << sum << std::endl;
  // trying 1st version
  std::cout << "1st version:\n";
  sum = 0;
  for(int i = 0; i<luck.size() - k; i++) {
    std::cout << "i: " << i << '\n';
    sum+=luck[i]; //RUNTIME ERROR
  }
  std::cout << "sum: " << sum << std::endl;
  // done
  return 0;
}

输出:

2nd version:
sum: 0
1st version:
i: 0
i: 1
i: 2
i: 3
i: 4
i: 5
i: 6
i: 7
i: 8
i: 9
i:

注:

sum 的输出没有发生。该应用程序会在没有进一步通知的情况下直接终止。这是一种未定义的行为可能表现出来的方式。分段错误是另一个。

Live Demo on coliru