0
#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 it is giving correct output if I add

int boundary = luck.size() - k;

and replacing the condition of second 'for' loop by

i<boundary;

Here's the complete errorless code, again:

#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;
}
curiousguy
  • 8,038
  • 2
  • 40
  • 58
Surajkumar_cse
  • 165
  • 1
  • 11
  • 2
    Don't mix signed and unsigned. Also, what do you think `5 - 10` will give you? You don't have that many elements in the vector... – DeiDei Jun 17 '18 at 09:10
  • @DeiDei It isn't the mixing of signed and unsigned that's the problem, it's the fact unsigned is used at all to deal with natural numbers, like a number of elements in container. It's just a ridiculous design choice. – curiousguy Jun 17 '18 at 12:33

2 Answers2

4

You are mixing unsigned and signed in your for loop. Another way to make your code work is to change:

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

to:

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

Explanation:

luck.size() returns unsigned integer value (std::vector::size_type). When you subtract k from it it's still treated as unsigned integer. Because in your case k > luck.size(), the result is negative. When you assign negative value to unsigned integer, you will get huge positive number instead, so the loop will not stop correctly.

In second case, assignment (to signed int) treats rhs expression as signed and code works as expected.

Outshined
  • 709
  • 7
  • 22
0

As already stated by DeiDei, this is the result of unlucky mixing of signed and unsigned integer.

Please note, std::vector::size() returns size_t.

Depending on platform, this is usally a 32 bit or 64 bit unsigned. (size_t has the same number of bits like void*.)

In the 1st sample:

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

the following values occur:

luck.size(): (size_t)5

k: (int)10

luck.size() - k: (size_t)0xFFFFFFFFFFFFFFFB (assuming 64 bit size)

The comparison of i < luck.size() - k promotes i to size_t as well. So, iteration does not stop at 5. Hence, in the 1st sample code, you get an out-of-bound access in the loop.

In the 2nd sample:

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

the value is converted to int again.

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

This results simply in no iteration of loop.

Demo:

#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;
}

Output:

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:

Note:

The output of sum doesn't happen. The application simply dies without further notification. This is one kind how undefined behavior may manifest. A segmentation fault is another.

Live Demo on coliru

Scheff's Cat
  • 19,528
  • 6
  • 28
  • 56
  • "_size_t has the same number of bits like void*_" why is that so? – curiousguy Jun 17 '18 at 12:31
  • @curiousguy This was my sloppy abbreviation / rule of thumb for _`std::size_t` can safely store the value of any non-member pointer, in which case it is synonymous with `std::uintptr_t`_ which in turn is an _unsigned integer type capable of holding a pointer_. Do you think this was a bit too sloppy? (The quotes are from cppreference.com.) – Scheff's Cat Jun 17 '18 at 13:53