6

I have a vector:

std::vector<int> vec = {1, 2, 3};

And I want to make a reverse for loop. It works, when I write:

for(int i = vec.size() - 1; i >= 0; --i) {
    std::cout << i << std::endl; // 2, 1, 0
}

But I get a very large number (like 18446744073709223794) if I write:

for(size_t i = vec.size() - 1; i >= 0; --i) {
    std::cout << i << std::endl;
}

But they both work when I write:

for(int i = 0; i < vec.size() - 1; ++i) {
    std::cout << i << std::endl; // 1, 2, 3
}

// Or
for(size_t i = 0; i < vec.size() - 1; ++i) {
    std::cout << i << std::endl; // 1, 2, 3
}

Why do I get the wrong size of the vector when I use size_t?

I think there is a problem with the conversion.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
asd
  • 266
  • 7
  • 15
  • Are you aware of the iterators? They are meant for this job. – Yunnosch Jun 13 '20 at 09:08
  • 1
    Use `vec.rbegin()` and `vec.rend()` to iterate backwards. – John Zwinck Jun 13 '20 at 09:10
  • 3
    @Yunnosch Yes, but I want to know why my code does not work so – asd Jun 13 '20 at 09:11
  • Sorry, you got two "agrees" on your comment, so the misunderstanding is probably on my side. But what do you mean by "I want to know why my code does not work so" ? Why your code does not work as it is? Why your code does not work by using iterators? – Yunnosch Jun 13 '20 at 09:14
  • @Yunnosch Yes, I just wanted to know, why my code does not work with size_t. – asd Jun 13 '20 at 09:19
  • @JohnZwinck: Covered this in my answer. – einpoklum Jun 13 '20 at 09:33
  • Does this answer your question? [Iterating over a vector in reverse direction](https://stackoverflow.com/questions/4205720/iterating-over-a-vector-in-reverse-direction) – Nick is tired Jun 13 '20 at 18:22
  • @Nick I were not looking for how to make for loop with reverse. I just wanted to know why me code does not work with `size_t` – asd Jun 13 '20 at 18:25
  • @SKIP *"As you've noted, the problem with a condition of i >= 0 when it's unsigned is that the condition is always true."* - First line of first answer – Nick is tired Jun 13 '20 at 18:26
  • But if you prefer then there's always: https://stackoverflow.com/questions/31659368/for-loop-exit-condition-size-t-vs-int – Nick is tired Jun 13 '20 at 18:32
  • Why *should* your code work? Asking why it doesn't is just asking for another definition of how the language works. – philipxy Jun 14 '20 at 06:58

2 Answers2

9

Let the compiler tell you what's wrong!

If you compiled your program with warnings enabled, the compiler would tell you something like this:

<source>: In function 'int main()':

7:43: warning: comparison of unsigned expression in '>= 0' is always true [-Wtype-limits]
    7 |     for(std::size_t i = vec.size() - 1; i >= 0; --i) {
      |                                         ~~^~~~

Why is that? It's because std::size_t is an unsigned type in C++; it only represents non-negative numbers. Read more about turning on warnings and why it's important: Why should I always enable compiler warnings?

So, how should we reverse-iterate?

I've decided to split my answer here off to a separate question, independent of OP's bug. Please go read it.

einpoklum
  • 118,144
  • 57
  • 340
  • 684
  • Thank you for a great answer. Why you use in option 1 `std::crbegin` and `std::crend` is there will be any difference If I use `std::rbegin` and `std::rend`? – asd Jun 13 '20 at 09:50
  • @SKIP: `crbegin()` and `crend() gives you `vector::const_iterator`s, guaranteeing you wont change the vector's content through the iterator. – einpoklum Jun 13 '20 at 10:03
6

The problem is that size_t is an unsigned integer, i.e. it can only have positive values. When you decrease 0 for an unsigned type an underflow happens and the result is usually the largest integer representable by that type, e.g. 18446744073709223794 in your case. Finally the check for i >= 0 is always true for any unsigned type and your loop will never terminate.

Haatschii
  • 9,021
  • 10
  • 58
  • 95