'What's the best way to do a backwards loop in C/C#/C++?

I need to move backwards through an array, so I have code like this:

for (int i = myArray.Length - 1; i >= 0; i--)
{
    // Do something
    myArray[i] = 42;
}

Is there a better way of doing this?

Update: I was hoping that maybe C# had some built-in mechanism for this like:

foreachbackwards (int i in myArray)
{
    // so easy
}

Update 2: There are better ways. Rune takes the prize with:

for (int i = myArray.Length; i-- > 0; )
{    
    //do something
}
//or
for (int i = myArray.Length; i --> 0; )
{
    // do something
}

which looks even better in regular C (thanks to Twotymz):

for (int i = lengthOfArray; i--; )
{    
    //do something
}


Solution 1:[1]

In C++ you basicially have the choice between iterating using iterators, or indices. Depending on whether you have a plain array, or a std::vector, you use different techniques.

Using std::vector

Using iterators

C++ allows you to do this using std::reverse_iterator:
for(std::vector<T>::reverse_iterator it = v.rbegin(); it != v.rend(); ++it) {
    /* std::cout << *it; ... */
}

Using indices

The unsigned integral type returned by `std::vector::size` is *not* always `std::size_t`. It can be greater or less. This is crucial for the loop to work.
for(std::vector<int>::size_type i = someVector.size() - 1; 
    i != (std::vector<int>::size_type) -1; i--) {
    /* std::cout << someVector[i]; ... */
}

It works, since unsigned integral types values are defined by means of modulo their count of bits. Thus, if you are setting -N, you end up at (2 ^ BIT_SIZE) -N

Using Arrays

Using iterators

We are using `std::reverse_iterator` to do the iterating.
for(std::reverse_iterator<element_type*> it(a + sizeof a / sizeof *a), itb(a); 
    it != itb; 
    ++it) {
    /* std::cout << *it; .... */
}

Using indices

We can safely use `std::size_t` here, as opposed to above, since `sizeof` always returns `std::size_t` by definition.
for(std::size_t i = (sizeof a / sizeof *a) - 1; i != (std::size_t) -1; i--) {
   /* std::cout << a[i]; ... */
}

Avoiding pitfalls with sizeof applied to pointers

Actually the above way of determining the size of an array sucks. If a is actually a pointer instead of an array (which happens quite often, and beginners will confuse it), it will silently fail. A better way is to use the following, which will fail at compile time, if given a pointer:
template<typename T, std::size_t N> char (& array_size(T(&)[N]) )[N];

It works by getting the size of the passed array first, and then declaring to return a reference to an array of type char of the same size. char is defined to have sizeof of: 1. So the returned array will have a sizeof of: N * 1, which is what we are looking for, with only compile time evaluation and zero runtime overhead.

Instead of doing

(sizeof a / sizeof *a)

Change your code so that it now does

(sizeof array_size(a))

Solution 2:[2]

In C#, using Visual Studio 2005 or later, type 'forr' and hit [TAB] [TAB]. This will expand to a for loop that goes backwards through a collection.

It's so easy to get wrong (at least for me), that I thought putting this snippet in would be a good idea.

That said, I like Array.Reverse() / Enumerable.Reverse() and then iterate forwards better - they more clearly state intent.

Solution 3:[3]

I would always prefer clear code against 'typographically pleasing' code. Thus, I would always use :

for (int i = myArray.Length - 1; i >= 0; i--)  
{  
    // Do something ...  
}    

You can consider it as the standard way to loop backwards.
Just my two cents...

Solution 4:[4]

In C# using Linq:

foreach(var item in myArray.Reverse())
{
    // do something
}

Solution 5:[5]

That's definitely the best way for any array whose length is a signed integral type. For arrays whose lengths are an unsigned integral type (e.g. an std::vector in C++), then you need to modify the end condition slightly:

for(size_t i = myArray.size() - 1; i != (size_t)-1; i--)
    // blah

If you just said i >= 0, this is always true for an unsigned integer, so the loop will be an infinite loop.

Solution 6:[6]

Looks good to me. If the indexer was unsigned (uint etc), you might have to take that into account. Call me lazy, but in that (unsigned) case, I might just use a counter-variable:

uint pos = arr.Length;
for(uint i = 0; i < arr.Length ; i++)
{
    arr[--pos] = 42;
}

(actually, even here you'd need to be careful of cases like arr.Length = uint.MaxValue... maybe a != somewhere... of course, that is a very unlikely case!)

Solution 7:[7]

In C I like to do this:


int i = myArray.Length;
while (i--) {
  myArray[i] = 42;
}

C# example added by MusiGenesis:

{int i = myArray.Length; while (i-- > 0)
{
    myArray[i] = 42;
}}

Solution 8:[8]

The best way to do that in C++ is probably to use iterator (or better, range) adaptors, which will lazily transform the sequence as it is being traversed.

Basically,

vector<value_type> range;
foreach(value_type v, range | reversed)
    cout << v;

Displays the range "range" (here, it's empty, but i'm fairly sure you can add elements yourself) in reverse order. Of course simply iterating the range is not much use, but passing that new range to algorithms and stuff is pretty cool.

This mechanism can also be used for much more powerful uses:

range | transformed(f) | filtered(p) | reversed

Will lazily compute the range "range", where function "f" is applied to all elements, elements for which "p" is not true are removed, and finally the resulting range is reversed.

Pipe syntax is the most readable IMO, given it's infix. The Boost.Range library update pending review implements this, but it's pretty simple to do it yourself also. It's even more cool with a lambda DSEL to generate the function f and the predicate p in-line.

Solution 9:[9]

I prefer a while loop. It's more clear to me than decrementing i in the condition of a for loop

int i = arrayLength;
while(i)
{
    i--;
    //do something with array[i]
}

Solution 10:[10]

// this is how I always do it
for (i = n; --i >= 0;){
   ...
}

Solution 11:[11]

i do this

if (list.Count > 0)
    for (size_t i = list.Count - 1; i >= 0; i--)
    {
        //do your thing
    
        if (i == 0) //for preventing unsigned wrap
            break;
    }

but for some reason visual studio 2019 gets angry and warns me "ill-defined loop" or something.. it doesnt trust me

Solution 12:[12]

I'd use the code in the original question, but if you really wanted to use foreach and have an integer index in C#:

foreach (int i in Enumerable.Range(0, myArray.Length).Reverse())
{
    myArray[i] = 42; 
}

Solution 13:[13]

For C++:

As mentioned by others, when possible (i.e. when you only want each element at a time) it is strongly preferable to use iterators to both be explicit and avoid common pitfalls. Modern C++ has a more concise syntax for that with auto:

std::vector<int> vec = {1,2,3,4};
for (auto it = vec.rbegin(); it != vec.rend(); ++it) {
    std::cout<<*it<<" ";
}

prints 4 3 2 1 .

You can also modify the value during the loop:

std::vector<int> vec = {1,2,3,4};
for (auto it = vec.rbegin(); it != vec.rend(); ++it) {
    *it = *it + 10;
    std::cout<<*it<<" ";
}

leading to 14 13 12 11 being printed and {11, 12, 13, 14} being in the std::vector afterwards.

If you don't plan on modifying the value during the loop, you should make sure that you get an error when you try to do that by accident, similarly to how one might write for(const auto& element : vec). This is possible like this:

std::vector<int> vec = {1,2,3,4};
for (auto it = vec.crbegin(); it != vec.crend(); ++it) { // used crbegin()/crend() here...
    *it = *it + 10; // ... so that this is a compile-time error
    std::cout<<*it<<" ";
}

The compiler error in this case for me is:

/tmp/main.cpp:20:9: error: assignment of read-only location ‘it.std::reverse_iterator<__gnu_cxx::__normal_iterator<const int*, std::vector<int> > >::operator*()’
   20 |     *it = *it + 10;
      |     ~~~~^~~~~~~~~~

Also note that you should make sure not to use different iterator types together:

std::vector<int> vec = {1,2,3,4};
for (auto it = vec.rbegin(); it != vec.end(); ++it) { // mixed rbegin() and end()
    std::cout<<*it<<" ";
}

leads to the verbose error:

/tmp/main.cpp: In function ‘int main()’:
/tmp/main.cpp:19:33: error: no match for ‘operator!=’ (operand types are ‘std::reverse_iterator<__gnu_cxx::__normal_iterator<int*, std::vector<int> > >’ and ‘std::vector<int>::iterator’ {aka ‘__gnu_cxx::__normal_iterator<int*, std::vector<int> >’})
   19 | for (auto it = vec.rbegin(); it != vec.end(); ++it) {
      |                              ~~ ^~ ~~~~~~~~~
      |                              |            |
      |                              |            std::vector<int>::iterator {aka __gnu_cxx::__normal_iterator<int*, std::vector<int> >}
      |                              std::reverse_iterator<__gnu_cxx::__normal_iterator<int*, std::vector<int> > >

If you have C-style arrays on the stack, you can do things like this:

int vec[] = {1,2,3,4};
for (auto it = std::crbegin(vec); it != std::crend(vec); ++it) {
    std::cout<<*it<<" ";
}

If you really need the index, consider the following options:

  • check the range, then work with signed values, e.g.:
void loop_reverse(std::vector<int>& vec) {
    if (vec.size() > static_cast<size_t>(std::numeric_limits<int>::max())) {
        throw std::invalid_argument("Input too large");
    }
    const int sz = static_cast<int>(vec.size());
    for(int i=sz-1; i >= 0; --i) {
        // do something with i
    }
}
  • Work with unsigned values, be careful, and add comments, e.g.:
void loop_reverse2(std::vector<int>& vec) {
    for(size_t i=vec.size(); i-- > 0;) { // reverse indices from N-1 to 0
        // do something with i
    }
}
  • calculate the actual index separately, e.g.:
void loop_reverse3(std::vector<int>& vec) {
    for(size_t offset=0; offset < vec.size(); ++offset) {
        const size_t i = vec.size()-1-offset; // reverse indices from N-1 to 0
        // do something with i
    }
}

Solution 14:[14]

I'm going to try answering my own question here, but I don't really like this, either:

for (int i = 0; i < myArray.Length; i++)
{
    int iBackwards = myArray.Length - 1 - i; // ugh
    myArray[iBackwards] = 666;
}