<p>There are two kinds of for loops: the kind that Python has, also called a &quot;foreach&quot;:</p>
<pre><code>for i in [1, 2, 3]:
  print(i)
</code></pre>
<p>and the kind that C has, which is syntactically heavy:</p>
<pre><code>int arr[] = { 1, 2, 3 };
for (int i = 0; i &lt; 3; ++i)
  printf(&quot;%d\n&quot;, arr[i]);
</code></pre>
<p>Some languages, such as C#, have both, but I've noticed that many modern languages only have the foreach.</p>
<p>What are some advantages and disadvantages to allowing each kind?</p>

<language-design><for-loops><foreach-loop>
What are advantages and disadvantages of C-style for loops?
CC BY-SA 4.0
2023-07-26T08:26:43.677Z
Relevant cross-site: [Why should I use foreach instead of for (int i=0; i<length; i++) in loops?](https://stackoverflow.com/questions/4383250/)
Karl Knechtel
<h1>C-style loops can allow for arbitrary increments</h1>
<p>This is especially visible when the increment is some non-constant calculation, like when I was trying to implement an optimized prime checker in Kotlin, which doesn’t have C style for loops. As noted in the comments, you can also go back (have a negative increment) using C-style for loops.</p>

CC BY-SA 4.0
2023-05-16T23:09:58.673Z
2023-05-16T23:57:55.143Z
2023-05-16T23:57:55.143Z
Seggan
CC BY-SA 4.0
2023-05-18T20:27:57.160Z
Janet has a `forv` function that is like a normal `for` range loop. It still automatically increments `i`, but it's a C-style for loop internally, and you can still modify `i`.
naffetS
CC BY-SA 4.0
2023-07-05T15:44:35.783Z
This is nice when you've got variable length sequences packed into an array.  For example, high-throughput processing of UTF-8 encoded strings; the first byte tells you how much to increment by to get the the next codepoint.
Mike Samuel
CC BY-SA 4.0
2023-05-16T23:56:15.197Z
Similarly, they also allow you to go _back_ on your loop, that is to modify your iteration variable in the middle of execution. IIRC bubble-sort is slightly quicker if you go back 1 iteration after swapping values?
kouta-kun
<h1>The C style doesn't work with parallel programming</h1>
<p>Some languages would want to add some built-in support for parallel programming in the basic looping constructs. A C style for doesn't work well in this case. If the language has only C style for, it would surprise the programmer when they want to change something to parallel.</p>
<p>There are cases that a foreach cannot work well, for example in the cases with non-constant increment. But a for loop also doesn't fully replace foreach with parallel programming in consideration.</p>

CC BY-SA 4.0
2023-07-04T02:48:55.110Z
2023-07-04T02:48:55.110Z
user23013
CC BY-SA 4.0
2023-11-13T22:55:43.917Z
I would think that even a C-style loop could improve support for parallel programming if a language had a construct to indicate that the compiler may skip whatever subset of the remaining iterations would be most convenient, except that the third expression of the `for` loop would be run for all iterations prior to the last one executed (and possibly more than that, and that loops avoid having that section modify anything other than automatic objects whose address is not taken.
supercat
CC BY-SA 4.0
2023-07-26T15:28:40.677Z
I think [OpenMP](https://en.wikipedia.org/wiki/OpenMP) would disagree that C-style for-loops are hard to parallelize. Sure, you can write unparallelizable for-loops, but as you mention, you can do the same with foreach-style loops.
G. Sliepen
<p>Flexibility is both a pro and a con of C-style for-loops.</p>
<p>You can have a for-loop with an arbitrary setup, arbitrary condition and arbitrary &quot;increment&quot; expressions.</p>
<p>This also means that</p>
<pre><code>for (A; B; C) {
 body;
}
</code></pre>
<p>is just syntactic sugar for</p>
<pre><code>{ // Block limits scope of variable declarations in A.
  A;
  while (B) {
    body;
    C;
  }
}
</code></pre>
<p>... and depending on the specifics, having that syntactic sugar may not be worth it.</p>

CC BY-SA 4.0
2023-05-16T23:21:38.933Z
2023-07-05T17:50:34.510Z
2023-07-05T17:50:34.510Z
Jasmijn
CC BY-SA 4.0
2023-07-05T15:57:16.383Z
I think you can wrap the body in a labeled block and rewrite `continue` to `break body_label` thus `{ A; while (B) { body_label: { body; } C; } }`.  Obviously, `body_label` needs to be a label chosen to be distinct from any label previously used in `body`.
Mike Samuel
CC BY-SA 4.0
2023-05-17T01:15:38.810Z
They are kind of equivalent; a `continue` appearing in the body means something slightly different.
Pseudonym
CC BY-SA 4.0
2023-05-17T08:25:59.953Z
That's true, you'd need to replace any `continue;` with `C; continue;` for the equivalency to hold.
Jasmijn
<h1>Avoiding off-by-one errors</h1>
<p>If you're not concentrating, it it really easy to get an off-by-one error with a C-style <code>for</code> loop.</p>
<p>For example, if I want to loop 10 times:</p>
<pre class="lang-c prettyprint-override"><code>for (i=0; i&lt;=10; i++) {
  // do stuff
}
</code></pre>
<p>actually loops 11 times.</p>
<p>But,</p>
<pre class="lang-python prettyprint-override"><code>for i in range(10):
  # do stuff
</code></pre>
<p>is a lot harder to get wrong</p>

CC BY-SA 4.0
2023-05-18T17:00:11.157Z
2023-05-18T17:00:11.157Z
The Thonnu
CC BY-SA 4.0
2023-05-18T17:01:18.833Z
Depends on your range syntax; cf. Swift `0...10`, `0..<10`
Bbrk24
CC BY-SA 4.0
2023-05-18T17:02:40.237Z
@Bbrk24 sure, but I would still say it's harder to get wrong than the C-style for loop.
The Thonnu
CC BY-SA 4.0
2023-05-18T17:04:58.933Z
I tend to add a comment to my `for` loops which use `<=` instead of `<`, it's so rare that I want to make sure readers know it's intentional ....
Glorfindel
CC BY-SA 4.0
2023-07-26T15:30:27.227Z
for (i = start; i < end; ++i) { ... } is such a common pattern in C, that's not "not concentrating", that's "drunk while programming".
gnasher729
<p>One major advantage of a <code>foreach</code> loop is that it makes safe bounds check removals a lot easier for the compiler. A C-style loop requires the compiler to prove a relation between the index and the array while the <code>foreach</code> gets bounds check removal for basically free.</p>

CC BY-SA 4.0
2023-07-04T04:47:35.350Z
2023-07-04T05:03:57.040Z
2023-07-04T05:03:57.040Z
Oscar Smith
CC BY-SA 4.0
2023-07-05T15:42:12.337Z
This is true for arrays that never reduce in size, but it's not true for mutable, user-defined types that might be changed by the loop body, right?

`foreach` loops based on iterators are only as safe as the iterator implementation in the face of the loop body.

For a foreach loop to be safe and support user defined collections you need statically checkable non-mutation, probably either type enforced immutability, or an inability for the body to access the collection via aliases, or some kind of contract that the length doesn't decrease.
Mike Samuel
CC BY-SA 4.0
2023-07-05T15:54:19.443Z
A lot of languages make it undefined behavior to mutate a collection you are `foreach`ing over.
Oscar Smith
<p>For each is much more ergonomic, declarative, and can even make some optimisations possible like removing bounds checking.</p>
<p>However, compared to C style for loops it’s much less obvious how it compiles to efficient machine code, so in most languages for each is slower than an equivalent C style loop.</p>
<p>The exception is languages with zero cost abstraction, specifically ones with lots of static dispatch and inlining which can compile for each down to the same thing as a C style loop.</p>

CC BY-SA 4.0
2023-05-16T23:13:35.920Z
2023-05-16T23:14:32.807Z
2023-05-16T23:14:32.807Z
Charlie Lidbury
CC BY-SA 4.0
2023-05-16T23:15:20.740Z
I know Swift special-cases `Array` -- a foreach loop on an array is as efficient as the equivalent C code, but it's impossible to do that for any user-implemented type.
Bbrk24
CC BY-SA 4.0
2023-05-16T23:25:47.310Z
Same for Java’s arrays and Kotlin’s ranges
Seggan
<p><strong>1.</strong> C style loop allows <strong>joining multiple arrays by index</strong>:</p>
<pre><code>for (size_t i = 0; i &lt; a.size(); i++) {
  do_something_together(a[i], b[i]);
}
</code></pre>
<p>The use cases are the same as for the <code>join</code> statement in SQL:</p>
<pre><code>select a.x, b.y from a join b on (a.p == b.p)
</code></pre>
<p>Here also one may argue, &quot;keep all fields you would ever need together in one table&quot;. Unfortunately this does not always work and it may be more important things influencing the clarity of the code. There is often no obvious and easy construct to iterate over multiple arrays, having values at the same position of each array together. See <a href="https://stackoverflow.com/questions/12552277/whats-the-best-way-to-iterate-over-two-or-more-containers-simultaneously">this question</a> for the possible approaches, many of them look complex. This is difficult to add later and should be built into the language, envisioning something like</p>
<pre><code>for (ax: a join bx: b) {
  do_something_together(ax, bx);
}
</code></pre>
<p>Of course, to be efficient this should not work just by copying. It should be an assertion that the arrays have the same dimensions or otherwise just &quot;outer join&quot; (loop terminates after reaching the boundary of the shorter array).</p>
<p>I am mostly using the &quot;for each&quot; style loops, but some need to be reworked into &quot;old style&quot; loops if they use two or more arrays this way in the iteration.</p>
<p><strong>2.</strong> There are also cases when <strong>adjacent elements are needed</strong>:</p>
<pre><code>for (size_t i = 1; i &lt; a.size(); i++) {
  double difference = a[i] - a[i-1];
  ...
}
</code></pre>
<p>This needs precautions for the first or last member of the array, anyway you also need another member that is not available in the &quot;modern&quot; ranged loop. Algorithms like filtering, smoothing, differentiating and the like often need access to the values that are spread around the current index. Here is the access as required, for the 2D array, by Crank-Nicolson method, the golden classic of numeric computation (<a href="https://commons.wikimedia.org/wiki/File:Crank-Nicolson-stencil.svg" rel="nofollow noreferrer">image credit</a>):</p>
<p><a href="https://i.sstatic.net/QW471m.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/QW471m.png" alt="enter image description here" /></a></p>
<p><strong>3.</strong> There may be cases when just the <strong>number of the iteration is needed</strong>, like printing the numbered list. It is very stupid when you cannot easily get it and need to define and maintain a separate counter. The question has been asked <a href="https://stackoverflow.com/questions/6953128/need-iterator-when-using-range-based-for-loops">here</a>, and, again, most of solutions are just too complex to be practical.</p>
<p><strong>4.</strong> Least, not the last: identifying <strong>the first and the last iteration</strong>. The most obvious case is when all you need is to produce the comma delimited list of items: it must be no comma after the last item. See <a href="https://codereview.stackexchange.com/questions/207035/elegantly-exclude-part-of-an-operation-for-the-last-iteration-in-a-loop">this question</a> for all fun the people attempted. Surely the classic C++ look also looks ugly, but still:</p>
<pre><code>   for (int k = 0; k &lt; a.size(); k++) {
     if (k + 1 == a.size()) {
        // Last iteration
     }
     ...
   }
</code></pre>
<p>something like</p>
<pre><code>for (int x: a) {
  ...
  if (last x) {
     ...
  }      
}
</code></pre>
<p>may look nicer, but how can you take value and return something that depends on the position inside the loop. Due that <code>last</code> and <code>first</code> must likely be the keywords built into the language, or some system functions that are processed in a very specific way with the help of compiler.</p>
<p>Some of these problems are also solvable with C++ iterators but the syntax also looks quite cluttered.</p>
<p>P.S. This answer advocates that it is important to have a loop where the loop variable is just an integer, supporting the usual arithmetic and usable with any array. There is a comment that it does not need to be a typical C loop, a simpler syntax like <code>for int x in a .. b</code> would also suffice. But even if loops providing just a reference to the member of collection being iterated look very simple and clean in most cases, there are other cases where they cannot be easily used.</p>

CC BY-SA 4.0
2023-07-05T12:00:49.527Z
2023-07-26T09:44:48.997Z
2023-07-26T09:44:48.997Z
Audrius Meškauskas
CC BY-SA 4.0
2023-07-05T12:35:27.620Z
The first one is often mitigated by a `zip` function, but that doesn't help if you need to modify one or both of the arrays in-place.
Bbrk24
CC BY-SA 4.0
2023-07-19T08:03:32.913Z
All of these can more easily be solved by having an iterator over a range of numbers, such as Python's `range`.
xigoi
CC BY-SA 4.0
2023-07-19T08:07:35.247Z
Pyton's for x in range(1,5) is very comparable with a C style loop for (int x = 1; x < 5; x++) so of course you can do all the same with it and same about the Swift for i in 1...5 . C style loop is of course originally more complex (assignment, comparison, increment) but a typical C developer recognizes the most common simple case and immediately parses into "ranged" understanding.
Audrius Meškauskas
CC BY-SA 4.0
2023-07-26T08:14:24.713Z
Some languages, say PHP, supports defining both the index and the element in a foreach loop.
user23013
<p>A <code>foreach</code> loop is an instance of a <code>for</code> loop, and a <code>for</code> loop is an instance of a <code>while</code> loop. Each is less general than the next.<br />
In particular <code>foreach</code> is specially crafted to loop over items in some collections where both <code>for</code> and <code>while</code> give you control over the looping mechanism.</p>
<p>Here are some examples of <code>for</code> loops which may or may not be translatable to an equivalent <code>foreach</code>:</p>
<ul>
<li>Looping over a constant range:
<pre class="lang-c prettyprint-override"><code>for(int x = start; x ⩽ end; x += n) {}
</code></pre>
</li>
<li>Looping over a variable range:
<pre class="lang-c prettyprint-override"><code>int n = initialStride;
for(int x = start; x ⩽ end; x += n) {
    n = f(x);
}
</code></pre>
</li>
<li>Looping over an integral's digits:
<pre class="lang-c prettyprint-override"><code>for(
    int x = n, digit = x % radix;
    x ≠ 0;
    x = floor(x / radix), digit = x % radix
) {}
</code></pre>
</li>
<li>Following pointers:
<pre class="lang-c prettyprint-override"><code>struct S { struct S* next; }
for(struct S* p = start; p; p = p-&gt;next) {}
</code></pre>
</li>
<li>Iterating over a segmented list:
<pre class="lang-c prettyprint-override"><code>struct S { struct S* next; size_t length; int elems[length]; };
assert(start);
for(
    struct S* sp = start, size_t ep = 0;
    sp &amp;&amp; ep &lt; sp-&gt;length;
    (++ep == sp-&gt;length) ? (sp = sp-&gt;next, ep = 0) : 0
) {}
</code></pre>
</li>
<li>Iterating over multiple lists at once:
<pre class="lang-c prettyprint-override"><code>for(
    int (*lp)[] = &amp;xs,
    size_t i = 0,
    elem = (*lp)[0];
    i ≠ END;
    ++i,
    lp = (lp == &amp;xs ? &amp;ys : &amp;xs),
    elem = (*lp)[i]
) {}
</code></pre>
</li>
</ul>
<ul>
<li>Looping with initialisation and incrementation clauses being unrelated to the condition:
<pre class="lang-c prettyprint-override"><code>S* p;
for(xs.prealloc(); p = xs.next(); free(p)) {}
</code></pre>
</li>
</ul>
<p>In fact when writing macros, it is common to use <code>for</code>'s incrementation clause as a way to defer code evaluation.<br />
Here are some examples:</p>
<ul>
<li><code>lock</code>:
<pre class="lang-c prettyprint-override"><code>#define lock(mutex) _lock_impl(UNIQUE_ID(_lock_id_), mutex)
#define _lock_impl(id, mutex) mtx_lock(mutex); for(char id = 1; id--; mtx_unlock(mutex))
</code></pre>
Example use:
<pre class="lang-c prettyprint-override"><code>void f()
{
    static mtx_t mtx = GLBL_MUTEX_INIT;
    lock(mtx) {
        printf(&quot;synchronised output\n&quot;);
    }
}
</code></pre>
</li>
<li><code>with</code> resource:
<pre class="lang-c prettyprint-override"><code>#define with(init, deinit) _with_impl(UNIQUE_ID(_with_id_), init, deinit)
#define _with_impl(id, init, deinit) char id = 1; for(init; id--; deinit)
</code></pre>
Example use:
<pre class="lang-c prettyprint-override"><code>int main()
{
    with(FILE* f = fopen(&quot;./input.txt&quot;, &quot;r&quot;), fclose(f)) {
        fseek(f, 0, SEEK_END);
        long int length = ftell(f);
        fseek(f, 0, SEEK_SET);
        with(char* buf = malloc(length), free(buf)) {
            fread(buf, 1, length, f);
            printf(&quot;%s&quot;, buf);
        }
    }
}
</code></pre>
</li>
</ul>
<p>both assuming GNU C's <code>__COUNTER__</code> and</p>
<pre class="lang-c prettyprint-override"><code>#define UNIQUE_ID(prefix) CONCAT(prefix, __COUNTER__)
#define CONCAT(x, y) _CONCAT_IMPL(x, y)
#define _CONCAT_IMPL(x, y) x##y
</code></pre>

CC BY-SA 4.0
2023-07-01T22:13:30.507Z
2023-07-02T13:15:06.853Z
2023-07-02T13:15:06.853Z
Longinus
# What are advantages and disadvantages of C-style for loops?
Posted by: username_0 on 2023-05-16
There are two kinds of for loops: the kind that Python has, also called a "foreach":
for i in [1, 2, 3]:
  print(i)

and the kind that C has, which is syntactically heavy:
int arr[] = { 1, 2, 3 };
for (int i = 0; i < 3; ++i)
  printf("%d\n", arr[i]);

Some languages, such as C#, have both, but I've noticed that many modern languages only have the foreach.
What are some advantages and disadvantages to allowing each kind?
**Tags:** language-design for-loops foreach-loop
> **Comments:**
> **username_1**: Relevant cross-site: [Why should I use foreach instead of for (int i=0; i<length; i++) in loops?](https://stackoverflow.com/questions/4383250/)  
---
## 8 answers
### Answer by username_2 on 2023-05-16. Score: 12
# C-style loops can allow for arbitrary increments

This is especially visible when the increment is some non-constant calculation, like when I was trying to implement an optimized prime checker in Kotlin, which doesn’t have C style for loops. As noted in the comments, you can also go back (have a negative increment) using C-style for loops.
> **Comments:**
> **username_5** (2023-05-16): Similarly, they also allow you to go _back_ on your loop, that is to modify your iteration variable in the middle of execution. IIRC bubble-sort is slightly quicker if you go back 1 iteration after swapping values?  
> **username_3** (2023-05-18): Janet has a `forv` function that is like a normal `for` range loop. It still automatically increments `i`, but it's a C-style for loop internally, and you can still modify `i`.  
> **username_4** (2023-07-05): This is nice when you've got variable length sequences packed into an array.  For example, high-throughput processing of UTF-8 encoded strings; the first byte tells you how much to increment by to get the the next codepoint.  
---
### Answer by username_6 on 2023-07-04. Score: 11
# The C style doesn't work with parallel programming

Some languages would want to add some built-in support for parallel programming in the basic looping constructs. A C style for doesn't work well in this case. If the language has only C style for, it would surprise the programmer when they want to change something to parallel.

There are cases that a foreach cannot work well, for example in the cases with non-constant increment. But a for loop also doesn't fully replace foreach with parallel programming in consideration.
> **Comments:**
> **username_8** (2023-07-26): I think [OpenMP](https://en.wikipedia.org/wiki/OpenMP) would disagree that C-style for-loops are hard to parallelize. Sure, you can write unparallelizable for-loops, but as you mention, you can do the same with foreach-style loops.  
> **username_7** (2023-11-13): I would think that even a C-style loop could improve support for parallel programming if a language had a construct to indicate that the compiler may skip whatever subset of the remaining iterations would be most convenient, except that the third expression of the `for` loop would be run for all iterations prior to the last one executed (and possibly more than that, and that loops avoid having that section modify anything other than automatic objects whose address is not taken.  
---
### Answer by username_18 on 2023-07-01. Score: 8
A foreach loop is an instance of a for loop, and a for loop is an instance of a while loop. Each is less general than the next.
In particular foreach is specially crafted to loop over items in some collections where both for and while give you control over the looping mechanism.
Here are some examples of for loops which may or may not be translatable to an equivalent foreach:

Looping over a constant range:
for(int x = start; x ⩽ end; x += n) {}


Looping over a variable range:
int n = initialStride;
for(int x = start; x ⩽ end; x += n) {
    n = f(x);
}


Looping over an integral's digits:
for(
    int x = n, digit = x % radix;
    x ≠ 0;
    x = floor(x / radix), digit = x % radix
) {}


Following pointers:
struct S { struct S* next; }
for(struct S* p = start; p; p = p->next) {}


Iterating over a segmented list:
struct S { struct S* next; size_t length; int elems[length]; };
assert(start);
for(
    struct S* sp = start, size_t ep = 0;
    sp && ep < sp->length;
    (++ep == sp->length) ? (sp = sp->next, ep = 0) : 0
) {}


Iterating over multiple lists at once:
for(
    int (*lp)[] = &xs,
    size_t i = 0,
    elem = (*lp)[0];
    i ≠ END;
    ++i,
    lp = (lp == &xs ? &ys : &xs),
    elem = (*lp)[i]
) {}




Looping with initialisation and incrementation clauses being unrelated to the condition:
S* p;
for(xs.prealloc(); p = xs.next(); free(p)) {}



In fact when writing macros, it is common to use for's incrementation clause as a way to defer code evaluation.
Here are some examples:

lock:
#define lock(mutex) _lock_impl(UNIQUE_ID(_lock_id_), mutex)
#define _lock_impl(id, mutex) mtx_lock(mutex); for(char id = 1; id--; mtx_unlock(mutex))

Example use:
void f()
{
    static mtx_t mtx = GLBL_MUTEX_INIT;
    lock(mtx) {
        printf("synchronised output\n");
    }
}


with resource:
#define with(init, deinit) _with_impl(UNIQUE_ID(_with_id_), init, deinit)
#define _with_impl(id, init, deinit) char id = 1; for(init; id--; deinit)

Example use:
int main()
{
    with(FILE* f = fopen("./input.txt", "r"), fclose(f)) {
        fseek(f, 0, SEEK_END);
        long int length = ftell(f);
        fseek(f, 0, SEEK_SET);
        with(char* buf = malloc(length), free(buf)) {
            fread(buf, 1, length, f);
            printf("%s", buf);
        }
    }
}



both assuming GNU C's __COUNTER__ and
#define UNIQUE_ID(prefix) CONCAT(prefix, __COUNTER__)
#define CONCAT(x, y) _CONCAT_IMPL(x, y)
#define _CONCAT_IMPL(x, y) x##y
---
### Answer by username_9 on 2023-05-16. Score: 7
Flexibility is both a pro and a con of C-style for-loops.
You can have a for-loop with an arbitrary setup, arbitrary condition and arbitrary "increment" expressions.
This also means that
for (A; B; C) {
 body;
}

is just syntactic sugar for
{ // Block limits scope of variable declarations in A.
  A;
  while (B) {
    body;
    C;
  }
}

... and depending on the specifics, having that syntactic sugar may not be worth it.
> **Comments:**
> **username_10** (2023-05-17): They are kind of equivalent; a `continue` appearing in the body means something slightly different.  
> **username_9** (2023-05-17): That's true, you'd need to replace any `continue;` with `C; continue;` for the equivalency to hold.  
> **username_4** (2023-07-05): I think you can wrap the body in a labeled block and rewrite `continue` to `break body_label` thus `{ A; while (B) { body_label: { body; } C; } }`.  Obviously, `body_label` needs to be a label chosen to be distinct from any label previously used in `body`.  
---
### Answer by username_11 on 2023-05-18. Score: 6
Avoiding off-by-one errors
If you're not concentrating, it it really easy to get an off-by-one error with a C-style for loop.
For example, if I want to loop 10 times:
for (i=0; i<=10; i++) {
  // do stuff
}

actually loops 11 times.
But,
for i in range(10):
  # do stuff

is a lot harder to get wrong
> **Comments:**
> **username_0** (2023-05-18): Depends on your range syntax; cf. Swift `0...10`, `0..<10`  
> **username_11** (2023-05-18): @Bbrk24 sure, but I would still say it's harder to get wrong than the C-style for loop.  
> **username_12** (2023-05-18): I tend to add a comment to my `for` loops which use `<=` instead of `<`, it's so rare that I want to make sure readers know it's intentional ....  
> **username_13** (2023-07-26): for (i = start; i < end; ++i) { ... } is such a common pattern in C, that's not "not concentrating", that's "drunk while programming".  
---
### Answer by username_14 on 2023-07-04. Score: 6
One major advantage of a `foreach` loop is that it makes safe bounds check removals a lot easier for the compiler. A C-style loop requires the compiler to prove a relation between the index and the array while the `foreach` gets bounds check removal for basically free.
> **Comments:**
> **username_4** (2023-07-05): This is true for arrays that never reduce in size, but it's not true for mutable, user-defined types that might be changed by the loop body, right?

`foreach` loops based on iterators are only as safe as the iterator implementation in the face of the loop body.

For a foreach loop to be safe and support user defined collections you need statically checkable non-mutation, probably either type enforced immutability, or an inability for the body to access the collection via aliases, or some kind of contract that the length doesn't decrease.  
> **username_14** (2023-07-05): A lot of languages make it undefined behavior to mutate a collection you are `foreach`ing over.  
---
### Answer by username_15 on 2023-05-16. Score: 4
For each is much more ergonomic, declarative, and can even make some optimisations possible like removing bounds checking.

However, compared to C style for loops it’s much less obvious how it compiles to efficient machine code, so in most languages for each is slower than an equivalent C style loop.

The exception is languages with zero cost abstraction, specifically ones with lots of static dispatch and inlining which can compile for each down to the same thing as a C style loop.
> **Comments:**
> **username_0** (2023-05-16): I know Swift special-cases `Array` -- a foreach loop on an array is as efficient as the equivalent C code, but it's impossible to do that for any user-implemented type.  
> **username_2** (2023-05-16): Same for Java’s arrays and Kotlin’s ranges  
---
### Answer by username_16 on 2023-07-05. Score: 4
1. C style loop allows joining multiple arrays by index:
for (size_t i = 0; i < a.size(); i++) {
  do_something_together(a[i], b[i]);
}

The use cases are the same as for the join statement in SQL:
select a.x, b.y from a join b on (a.p == b.p)

Here also one may argue, "keep all fields you would ever need together in one table". Unfortunately this does not always work and it may be more important things influencing the clarity of the code. There is often no obvious and easy construct to iterate over multiple arrays, having values at the same position of each array together. See this question for the possible approaches, many of them look complex. This is difficult to add later and should be built into the language, envisioning something like
for (ax: a join bx: b) {
  do_something_together(ax, bx);
}

Of course, to be efficient this should not work just by copying. It should be an assertion that the arrays have the same dimensions or otherwise just "outer join" (loop terminates after reaching the boundary of the shorter array).
I am mostly using the "for each" style loops, but some need to be reworked into "old style" loops if they use two or more arrays this way in the iteration.
2. There are also cases when adjacent elements are needed:
for (size_t i = 1; i < a.size(); i++) {
  double difference = a[i] - a[i-1];
  ...
}

This needs precautions for the first or last member of the array, anyway you also need another member that is not available in the "modern" ranged loop. Algorithms like filtering, smoothing, differentiating and the like often need access to the values that are spread around the current index. Here is the access as required, for the 2D array, by Crank-Nicolson method, the golden classic of numeric computation (image credit):

3. There may be cases when just the number of the iteration is needed, like printing the numbered list. It is very stupid when you cannot easily get it and need to define and maintain a separate counter. The question has been asked here, and, again, most of solutions are just too complex to be practical.
4. Least, not the last: identifying the first and the last iteration. The most obvious case is when all you need is to produce the comma delimited list of items: it must be no comma after the last item. See this question for all fun the people attempted. Surely the classic C++ look also looks ugly, but still:
   for (int k = 0; k < a.size(); k++) {
     if (k + 1 == a.size()) {
        // Last iteration
     }
     ...
   }

something like
for (int x: a) {
  ...
  if (last x) {
     ...
  }      
}

may look nicer, but how can you take value and return something that depends on the position inside the loop. Due that last and first must likely be the keywords built into the language, or some system functions that are processed in a very specific way with the help of compiler.
Some of these problems are also solvable with C++ iterators but the syntax also looks quite cluttered.
P.S. This answer advocates that it is important to have a loop where the loop variable is just an integer, supporting the usual arithmetic and usable with any array. There is a comment that it does not need to be a typical C loop, a simpler syntax like for int x in a .. b would also suffice. But even if loops providing just a reference to the member of collection being iterated look very simple and clean in most cases, there are other cases where they cannot be easily used.
> **Comments:**
> **username_0** (2023-07-05): The first one is often mitigated by a `zip` function, but that doesn't help if you need to modify one or both of the arrays in-place.  
> **username_17** (2023-07-19): All of these can more easily be solved by having an iterator over a range of numbers, such as Python's `range`.  
> **username_16** (2023-07-19): Pyton's for x in range(1,5) is very comparable with a C style loop for (int x = 1; x < 5; x++) so of course you can do all the same with it and same about the Swift for i in 1...5 . C style loop is of course originally more complex (assignment, comparison, increment) but a typical C developer recognizes the most common simple case and immediately parses into "ranged" understanding.  
> **username_6** (2023-07-26): Some languages, say PHP, supports defining both the index and the element in a foreach loop.  
---
