while loops scale the best for large arrays. for...of loops are hands down the fastest when it comes to small data sets, but they scale poorly for large data sets. . forEach() and for...of were close enough that neither side should hang their hat on performance alone over the other.
Use a for loop when you know the loop should execute n times. Use a while loop for reading a file into a variable. Use a while loop when asking for user input. Use a while loop when the increment value is nonstandard.
range() function is implemented in C, so, its faster. On basis of disassembly, for loop is faster than while loop. On basis of disassembly, the while loop is slower than for loop.
"Do-While loop is the fastest loop in C programming".
In perl, they result in the same opcodes:
$ perl -MO=Concise -e 'for(;;) { print "foo\n" }'
a <@> leave[1 ref] vKP/REFC ->(end)
1 <0> enter ->2
2 <;> nextstate(main 2 -e:1) v ->3
9 <2> leaveloop vK/2 ->a
3 <{> enterloop(next->8 last->9 redo->4) v ->4
- <@> lineseq vK ->9
4 <;> nextstate(main 1 -e:1) v ->5
7 <@> print vK ->8
5 <0> pushmark s ->6
6 <$> const[PV "foo\n"] s ->7
8 <0> unstack v ->4
-e syntax OK
$ perl -MO=Concise -e 'while(1) { print "foo\n" }'
a <@> leave[1 ref] vKP/REFC ->(end)
1 <0> enter ->2
2 <;> nextstate(main 2 -e:1) v ->3
9 <2> leaveloop vK/2 ->a
3 <{> enterloop(next->8 last->9 redo->4) v ->4
- <@> lineseq vK ->9
4 <;> nextstate(main 1 -e:1) v ->5
7 <@> print vK ->8
5 <0> pushmark s ->6
6 <$> const[PV "foo\n"] s ->7
8 <0> unstack v ->4
-e syntax OK
Likewise in GCC:
#include <stdio.h>
void t_while() {
while(1)
printf("foo\n");
}
void t_for() {
for(;;)
printf("foo\n");
}
.file "test.c"
.section .rodata
.LC0:
.string "foo"
.text
.globl t_while
.type t_while, @function
t_while:
.LFB2:
pushq %rbp
.LCFI0:
movq %rsp, %rbp
.LCFI1:
.L2:
movl $.LC0, %edi
call puts
jmp .L2
.LFE2:
.size t_while, .-t_while
.globl t_for
.type t_for, @function
t_for:
.LFB3:
pushq %rbp
.LCFI2:
movq %rsp, %rbp
.LCFI3:
.L5:
movl $.LC0, %edi
call puts
jmp .L5
.LFE3:
.size t_for, .-t_for
.section .eh_frame,"a",@progbits
.Lframe1:
.long .LECIE1-.LSCIE1
.LSCIE1:
.long 0x0
.byte 0x1
.string "zR"
.uleb128 0x1
.sleb128 -8
.byte 0x10
.uleb128 0x1
.byte 0x3
.byte 0xc
.uleb128 0x7
.uleb128 0x8
.byte 0x90
.uleb128 0x1
.align 8
.LECIE1:
.LSFDE1:
.long .LEFDE1-.LASFDE1
.LASFDE1:
.long .LASFDE1-.Lframe1
.long .LFB2
.long .LFE2-.LFB2
.uleb128 0x0
.byte 0x4
.long .LCFI0-.LFB2
.byte 0xe
.uleb128 0x10
.byte 0x86
.uleb128 0x2
.byte 0x4
.long .LCFI1-.LCFI0
.byte 0xd
.uleb128 0x6
.align 8
.LEFDE1:
.LSFDE3:
.long .LEFDE3-.LASFDE3
.LASFDE3:
.long .LASFDE3-.Lframe1
.long .LFB3
.long .LFE3-.LFB3
.uleb128 0x0
.byte 0x4
.long .LCFI2-.LFB3
.byte 0xe
.uleb128 0x10
.byte 0x86
.uleb128 0x2
.byte 0x4
.long .LCFI3-.LCFI2
.byte 0xd
.uleb128 0x6
.align 8
.LEFDE3:
.ident "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3"
.section .note.GNU-stack,"",@progbits
So I guess the answer is, they're the same in many compilers. Of course, for some other compilers this may not necessarily be the case, but chances are the code inside of the loop is going to be a few thousand times more expensive than the loop itself anyway, so who cares?
There's not much reason to prefer one over the other. I do think that while(1)
and particularly while(true)
are more readable than for(;;)
, but that's just my preference.
Using GCC, they both seem to compile to the same assembly language:
L2:
jmp L2
There is no difference according to the standard. 6.5.3/1 has:
The for statement
for ( for-init-statement ; conditionopt ; expressionopt ) statement
is equivalent to
{
for-init-statement
while ( condition ) {
statement
expression ;
}
}
And 6.5.3/2 has:
Either or both of the condition and the expression can be omitted. A missing condition makes the implied while clause equivalent to while(true).
So according to the C++ standard the code:
for (;;);
is exactly the same as:
{
while (true) {
;
;
}
}
for(;;)
is one less character to type if you want to go in that direction to optimize things.
The Visual C++ compiler used to emit a warning for
while (1)
(constant expression) but not for
for (;;)
I've continued the practice of preferring for (;;)
for that reason, but I don't know if the compiler still does that these days.
Turbo C with this old compilers for(;;)
results in faster code then while(1)
.
Today gcc, Visual C (I think almost all) compilers optimize well, and CPUs with 4.7 MHz are rarely used.
In those days a for( i=10; i; i-- )
was faster than for( i=1; i <=10; i++ )
, because compare i
is 0, results in a CPU-Zero-Flag conditional Jump. And the Zero-Flag was modified with the last decrement operation ( i-- )
, no extra cmp-operation is needed.
call __printf_chk
decl %ebx %ebx=iterator i
jnz .L2
movl -4(%ebp), %ebx
leave
and here with for(i=1; i<=10; i++)
with extra cmpl:
call __printf_chk
incl %ebx
cmpl $11, %ebx
jne .L2
movl -4(%ebp), %ebx
leave
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With