Paul Espina
Paul Espina

Reputation: 25

Is there a bug when using for loop with vectors?

The problem is that when i do "for(int i = 0; i < vector.size() - 1; i++)", it gives me a "vector subscript out of range" error. However if I put the vector.size() - 1 in a variable, it works. Is this a glitch or am I just missing something?

this works:

    int sizePos = positionsX.size() - 1;

    for (int i = 0; i < sizePos; i++) {
        if (snake.getX() == positionsX[i] && snake.getY() == positionsY[i]) {
            gameOver = true;
            std::cout << as << std::endl;
            as++;
        }

        if (apple.getX() == positionsX[i] && apple.getY() == positionsY[i]) {
            apple.eat();
        }
    }

and this does not:

    for (int i = 0; i < positionsX.size() - 1; i++) {
        if (snake.getX() == positionsX[i] && snake.getY() == positionsY[i]) {
            gameOver = true;
            std::cout << as << std::endl;
            as++;
        }

        if (apple.getX() == positionsX[i] && apple.getY() == positionsY[i]) {
            apple.eat();
        }
    }

Upvotes: 1

Views: 128

Answers (3)

Vlad from Moscow
Vlad from Moscow

Reputation: 311028

You did not point out what means "does not work" that is in which case the code does not work.

Nevertheless answering your question

Is there a bug when using for loop with vectors?

I'll say that the code indeed has bugs.

First of all the size of vectors is defined as unsigned integral type. The type int in general can not accomodate all values of the unsigned integral type.

In this expression

positionsX.size() - 1

there is used the arithmetic of unsigned integral types. That is the expression positionsX.size() - 1 is converted to the unsigned integral type and will be equal to the maximum value for the type provided that positionsX.size() is equal to 0. That is the expression in fact evaluates as

static_cast<decltype( positionsX )::size_type>( positionsX.size() - 1 );

For example for an empty vector you can get the following result

#include <iostream>
#include <vector>

int main()
{
    std::vector<int> positionsX;

    auto size = static_cast<decltype( positionsX )::size_type>( positionsX.size() - 1 );

    std::cout << size << '\n';
}

The console output is

18446744073709551615

In the first case when an intermediate variable is used

int sizePos = positionsX.size() - 1;

the result of the expression

positionsX.size() - 1

can be truncated to fit an object of type int and corresponding indices will be valid (though the range can be in whole invalid that is it can be less than the actual range).

Thus your problem is that you are using the type int instead of the original type

decltype( positionX )::size_type

Also the loops omit the last element of the vector.

The correct loop can look the following way

for (decltype( positionX )::size_type i = 0; i < positionsX.size(); i++) {
    //...
}

Or at least you should use the type size_t as the type of the variable i (though the first variant is more correct)

for ( size_t i = 0; i < positionsX.size(); i++) {
    //...
}

Upvotes: 2

Bathsheba
Bathsheba

Reputation: 234715

positionsX.size() is an unsigned type. If it's zero then subtracting 1 from it gives you the maximum value of the unsigned type due to wrap-around and the fact that the expression is evaluated in unsigned arithmetic!

Use

for (std::size_t i = 0; i + 1 < positionsX.size(); i++) {

instead, nothing that this will always omit the final element in the vector. If you don't want that then drop the + 1.

Upvotes: 7

Igor G
Igor G

Reputation: 2371

If positionsX vector is empty, then positionsX.size() - 1 evaluates to size_t(-1) which is a very big positive value.

When converted to int, as in your first snippet, that value would likely turn back into '-1'. And the loop body is skipped.

When used in comparision i < positionsX.size() - 1, the compiler converts i to unsigned size_t and the comparision yields true. The loop body is executed. And it attempts accessing positionsX[0] which isn't there...

Upvotes: 2

Related Questions