C++ reverse 'for' loop
Asked Answered
F

2

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.

Fled answered 13/6, 2020 at 9:5 Comment(11)
Are you aware of the iterators? They are meant for this job.Profession
Use vec.rbegin() and vec.rend() to iterate backwards.Hyperesthesia
@Profession Yes, but I want to know why my code does not work soFled
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?Profession
@Profession Yes, I just wanted to know, why my code does not work with size_t.Fled
@JohnZwinck: Covered this in my answer.Grays
Does this answer your question? Iterating over a vector in reverse directionKarakorum
@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_tFled
@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 answerKarakorum
But if you prefer then there's always: #31659868Karakorum
Why should your code work? Asking why it doesn't is just asking for another definition of how the language works.Diocesan
G
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.

Grays answered 13/6, 2020 at 9:12 Comment(2)
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?Fled
@SKIP: crbegin() and crend() gives you vector::const_iterator`s, guaranteeing you wont change the vector's content through the iterator.Grays
R
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.

Rhythmandblues answered 13/6, 2020 at 9:10 Comment(2)
Why isn't it an uneven number (e.g. like -1 / 255 for 8-bit integers)?Circumstance
size_t(-1) should be (on 64 bit systems) 2^64-1, i.e. an uneven number. I guess OP just picked any number the for loop printed, no necessarily the first one.Rhythmandblues

© 2022 - 2024 — McMap. All rights reserved.