For vs. while in C programming? - c

There are three loops in C: for, while, and do-while. What's the difference between them?
For example, it seems nearly all while statements can be replaced by for statements, right? Then, what's the advantage using while?

A while loop will always evaluate the condition first.
while (condition) {
//gets executed after condition is checked
}
A do/while loop will always execute
the code in the do{} block first
and then evaluate the condition.
do {
//gets executed at least once
} while (condition);
A for loop allows you to initiate a counter variable, a check condition, and a way to increment your counter all in one line.
for (int x = 0; x < 100; x++) {
//executed until x >= 100
}
At the end of the day, they are all still loops, but they offer some flexibility as to how they are executed.
Here is a great explanation of the reasoning behind the use of each different type of loop that may help clear things up. Thanks clyfe
The main difference between the for's
and the while's is a matter of
pragmatics: we usually use for when
there is a known number of iterations,
and use while constructs when the
number of iterations in not known in
advance. The while vs do ... while
issue is also of pragmatics, the
second executes the instructions once
at start, and afterwards it behaves
just like the simple while.
For loops are especially nice because they are concise. In order for this for loop:
for (int x = 0; x < 100; x++) {
//executed until x >= 100
}
to be written as a while loop, you'd have to do the following:
int count = 0;
while (count < 100) {
//do stuff
count++;
}
In this case, there's just more stuff to keep up with and the count++; could get lost in the logic. This could end up being troublesome depending on where count gets incremented, and whether or not it should get incremented before or after the loop's logic. With a for loop, your counter variable is always incremented before the next iteration of the loop, which adds some uniformity to your code.
For the sake of completeness, it's probably meaningful to talk about break and continue statements here which come in handy when doing loop processing.
break will instantly terminate the current loop and no more iterations will be executed.
//will only run "do stuff" twice
for (int x = 0; x < 100; x++) {
if (x == 2) {
break;
}
//do stuff
}
continue will terminate the current iteration and move on to the next one.
//will run "do stuff" until x >= 100 except for when x = 2
for (int x = 0; x < 100; x++) {
if (x == 2) {
continue;
}
//do stuff
}
Note that in a for loop, continue evaluates the part3 expression of for (part1; part2; part3); in contrast, in a while loop, it just jumps to re-evaluate the loop condition.

If there is a strong concern about speed and performance, the best approach is to verify the code produced by the compiler at the assembly level.
For instance, the following code shows that the "do-while" is a bit faster. This because the "jmp" instruction is not used by the "do-while" loop.
BTW, in this specific example, the worst case is given by the "for" loop. :))
int main(int argc, char* argv[])
{
int i;
char x[100];
// "FOR" LOOP:
for (i=0; i<100; i++ )
{
x[i] = 0;
}
// "WHILE" LOOP:
i = 0;
while (i<100 )
{
x[i++] = 0;
}
// "DO-WHILE" LOOP:
i = 0;
do
{
x[i++] = 0;
}
while (i<100);
return 0;
}
// "FOR" LOOP:
010013C8 mov dword ptr [ebp-0Ch],0
010013CF jmp wmain+3Ah (10013DAh)
for (i=0; i<100; i++ )
{
x[i] = 0;
010013D1 mov eax,dword ptr [ebp-0Ch] <<< UPDATE i
010013D4 add eax,1
010013D7 mov dword ptr [ebp-0Ch],eax
010013DA cmp dword ptr [ebp-0Ch],64h <<< TEST
010013DE jge wmain+4Ah (10013EAh) <<< COND JUMP
010013E0 mov eax,dword ptr [ebp-0Ch] <<< DO THE JOB..
010013E3 mov byte ptr [ebp+eax-78h],0
010013E8 jmp wmain+31h (10013D1h) <<< UNCOND JUMP
}
// "WHILE" LOOP:
i = 0;
010013EA mov dword ptr [ebp-0Ch],0
while (i<100 )
{
x[i++] = 0;
010013F1 cmp dword ptr [ebp-0Ch],64h <<< TEST
010013F5 jge wmain+6Ah (100140Ah) <<< COND JUMP
010013F7 mov eax,dword ptr [ebp-0Ch] <<< DO THE JOB..
010013FA mov byte ptr [ebp+eax-78h],0
010013FF mov ecx,dword ptr [ebp-0Ch] <<< UPDATE i
01001402 add ecx,1
01001405 mov dword ptr [ebp-0Ch],ecx
01001408 jmp wmain+51h (10013F1h) <<< UNCOND JUMP
}
// "DO-WHILE" LOOP:
i = 0;
. 0100140A mov dword ptr [ebp-0Ch],0
do
{
x[i++] = 0;
01001411 mov eax,dword ptr [ebp-0Ch] <<< DO THE JOB..
01001414 mov byte ptr [ebp+eax-78h],0
01001419 mov ecx,dword ptr [ebp-0Ch] <<< UPDATE i
0100141C add ecx,1
0100141F mov dword ptr [ebp-0Ch],ecx
01001422 cmp dword ptr [ebp-0Ch],64h <<< TEST
01001426 jl wmain+71h (1001411h) <<< COND JUMP
}
while (i<100);

For the sake of readability

They're all interchangeable; you could pick one type and use nothing but that forever, but usually one is more convenient for a given task. It's like saying "why have switch, you can just use a bunch of if statements" -- true, but if it's a common pattern to check a variable for a set of values, it's convenient and much easier to read if there's a language feature to do that

If you want a loop to execute while a condition is true, and not for a certain number of iterations, it is much easier for someone else to understand:
while (cond_true)
than something like this:
for (; cond_true ; )

Remember, a for loop is essentially a fancy while loop. They're the same thing.
while <some condition is true> {
// do some stuff
// possibly do something to change the condition
}
for ( some var, <some condition is true>; increment var ) {
}
The advantage of a for loop is that it's harder to accidentally do an infinite loop. Or rather, it's more obvious when you do one because you generally put the loop var in the initial statement.
A while loop is more clear when you're not doing a standard incrementing pattern. For example:
int x = 1;
while( x != 10 ) {
if ( some condition )
x = 10;
else
x += 5;
}

You should use such a loop, that most fully conforms to your needs.
For example:
for(int i = 0; i < 10; i++)
{
print(i);
}
//or
int i = 0;
while(i < 10)
{
print(i);
i++;
}
Obviously, in such situation, "for" looks better, than "while".
And "do while" shoud be used when some operations must be done already before the moment when condition of your loop will be checked.
Sorry for my bad english).

One common misunderstanding withwhile/for loops I've seen is that their efficiency differs. While loops and for loops are equally efficient. I remember my computer teacher from highschool told me that for loops are more efficient for iteration when you have to increment a number. That is not the case.
For loops are simply syntactically sugared while loops, and make iteration code faster to write.
When the compiler takes your code and compiles it, it is translating it into a form that is easier for the computer to understand and execute on a lower level (assembly). During this translation, the subtle differences between the while and for syntaxes are lost, and they become exactly the same.

A for suggest a fixed iteration using an index or variants on this scheme.
A while and do... while are constructions you use when there is a condition that must be checked each time (apart from some index-alike construction, see above). They differ in when the first execution of the condition check is performed.
You can use either construct, but they have their advantages and disadvantages depending on your use case.

I noticed some time ago that a For loop typically generates several more machine instructions than a while loop. However, if you look closely at the examples, which mirror my observations, the difference is two or three machine instructions, hardly worth much consideration.
Note, too, that the initializer for a WHILE loop can be eliminated by baking it into the code, e. g.:
static int intStartWith = 100;
The static modifier bakes the initial value into the code, saving (drum roll) one MOV instruction. Of greater significance, marking a variable as static moves it outside the stack frame. Variable alignment permitting, it may also produce slightly smaller code, too, since the MOV instruction and its operands take more room than, for example an integer, Boolean, or character value (either ANSI or Unicode).
However, if variables are aligned on 8 byte boundaries, a common default setting, an int, bool, or TCHAR baked into code costs the same number of bytes as a MOV instruction.

They are all the same in the work they do. You can do the same things using any of them. But for readability, usability, convenience etc., they differ.

A difference between while and do-while is that while checks the loop condition and if this is true, the body is executed and the condition checked again. The do-while checks the condition after execution of the body, so with do-while the body is executed at least one time.
Of course you can write a while loop as a do-while and vv, but this usually requires some code duplication.

One peculiarity of the do while is that you need a semi-colon after the while to complete. It is often used in macro definitions to execute several statements only once while constraining the impact of the macro. If macros where defined as blocks, some parsing errors may occur.
One explanation among others

For loops (at least considering C99) are superior to while loops because they limit the scope of the incremented variable(s).
Do while loops are useful when the condition is dependant on some inputs. They are the most seldom used of the three loop types.

Between for and while: while does not need initialization nor update statement, so it may look better, more elegant; for can have statements missing, one two or all, so it is the most flexible and obvious if you need initialization, looping condition and "update" before looping. If you need only loop condition (tested at the beginning of the loop) then while is more elegant.
Between for/while and do-while: in do-while the condition is evaluated at the end of the loop. More confortable if the loop must be executed at least once.

WHILE is more flexible. FOR is more concise in those instances in which it applies.
FOR is great for loops which have a counter of some kind, like
for (int n=0; n<max; ++n)
You can accomplish the same thing with a WHILE, of course, as others have pointed out, but now the initialization, test, and increment are broken across three lines. Possibly three widely-separated lines if the body of the loop is large. This makes it harder for the reader to see what you're doing. After all, while "++n" is a very common third piece of the FOR, it's certainly not the only possibility. I've written many loops where I write "n+=increment" or some more complex expression.
FOR can also work nicely with things other than a counter, of course. Like
for (int n=getFirstElementFromList(); listHasMoreElements(); n=getNextElementFromList())
Etc.
But FOR breaks down when the "next time through the loop" logic gets more complicated. Consider:
initializeList();
while (listHasMoreElements())
{
n=getCurrentElement();
int status=processElement(n);
if (status>0)
{
skipElements(status);
advanceElementPointer();
}
else
{
n=-status;
findElement(n);
}
}
That is, if the process of advancing may be different depending on conditions encountered while processing, a FOR statement is impractical. Yes, sometimes you could make it work with a complicated enough expressions, use of the ternary ?: operator, etc, but that usually makes the code less readable rather than more readable.
In practice, most of my loops are either stepping through an array or structure of some kind, in which case I use a FOR loop; or are reading a file or a result set from a database, in which case I use a WHILE loop ("while (!eof())" or something of that sort).

They are pretty much same except for do-while loop. The for loop is good when you have a counter kind of variable. It makes it obvious. while loop makes sense in cases where a flag is being checked as show below :
while (!done) {
if (some condtion)
done = true;
}

while and for statements can both be used for looping in programming. It will depend on the programmer as to whether the while loop or for loop is used. Some are comfortable using while loop and some are with for loop.
Use any loop you like. However, the do...while loop can be somewhat tricky in C programming.

/*
while loop
5 bucks
1 chocolate = 1 bucks
while my money is greater than 1 bucks
select chocolate
pay 1 bucks to the shopkeeper
money = money - 1
end
come to home and cant go to while shop because my money = 0 bucks
*/
#include<stdio.h>
int main(){
int money = 5;
while( money >= 1){
printf("inside the shopk and selecting chocolate\n");
printf("after selecting chocolate paying 1 bucks\n");
money = money - 1 ;
printf("my remaining moeny = %d\n", money);
printf("\n\n");
}
printf("dont have money cant go inside the shop, money = %d", money);
return 0;
}
infinite money
while( codition ){ // condition will always true ....infinite loop
statement(s)
}
please visit this video for better understanding
https://www.youtube.com/watch?v=eqDv2wxDMJ8&t=25s
/*
for loop
5 bucks
for my money is greater than equal to 1 bucks 0 money >= 1
select chocolate
pay 1 bucks to the shopkeeper
money = money - 1 1-1 => 0
end
*/
#include<stdio.h>
int main(){
int money = 5;
for( ; money >= 1; ){ 0>=1 false
printf("select chocolate \n");
printf("paying 1 bucks to the shopkeeper\n");
money = money - 1; 1-1 = 0
printf(" remaining money =%d\n", money);
printf("\n\n");
}
return 0;
}
For better understanding please visit https://www.youtube.com/watch?v=_vdvyzzp-R4&t=25s

Related

will gcc optimization remove for loop if it's only one iteration?

Im writing a real time DSP processing library.
My intention is to give it a flexibility to define input samples blockSize, while also having best possible performance in case of sample-by-sample processing, that is - single sample block size
I think I have to use volatile keyword defining loop variable since data processing will be using pointers to Inputs/Outputs.
This leads me to a question:
Will gcc compiler optimize this code
int blockSize = 1;
for (volatile int i=0; i<blockSize; i++)
{
foo()
}
or
//.h
#define BLOCKSIZE 1
//.c
for (volatile int i=0; i<BLOCKSIZE; i++)
{
foo()
}
to be same as simply calling body of the loop:
foo()
?
Thx
I think I have to use volatile keyword defining loop variable since data processing will be using pointers to Inputs/Outputs.
No, that doesn't make any sense. Only the input/output hardware registers themselves should be volatile. Pointers to them should be declared as pointer-to-volatile data, ie volatile uint8_t*. There is no need to make the pointer itself volatile, ie uint8_t* volatile //wrong.
As things stand now, you force the compiler to create a variable i and increase it, which will likely block loop unrolling optimizations.
Trying your code on gcc x86 with -O3 this is exactly what happens. No matter the size of BLOCKSIZE, it still generates the loop because of volatile. If I drop volatile it completely unrolls the loop up to BLOCKSIZE == 7 and replace it with a number of function calls. Beyond 8 it creates a loop (but keeps the iterator in a register instead of RAM).
x86 example:
for (int i=0; i<5; i++)
{
foo();
}
gives
call foo
call foo
call foo
call foo
call foo
But
for (volatile int i=0; i<5; i++)
{
foo();
}
gives way more inefficient
mov DWORD PTR [rsp+12], 0
mov eax, DWORD PTR [rsp+12]
cmp eax, 4
jg .L2
.L3:
call foo
mov eax, DWORD PTR [rsp+12]
add eax, 1
mov DWORD PTR [rsp+12], eax
mov eax, DWORD PTR [rsp+12]
cmp eax, 4
jle .L3
.L2:
For further study of the correct use of volatile in embedded systems, please see:
How to access a hardware register from firmware?
Using volatile in embedded C development
Since the loop variable is volatile it shouldn't optimize it. The compiler can not know wether i will be 1 when the condition is evaluated, so it has to keep the loop.
From the compiler point of view, the loop can run an indeterminite number of times until the condition is satisfied.
If you somehwere access hardware registers, then those should be declared volatile, which would make more sense, to the reader, and also allows the compiler to apply appropriate optimizations where possible.
volatile keyword says the compiler that the variable is side effects prone - ie it can be changed by something which is not visible for the compiler.
Because of that volatile variables have to read before every use and saved to their permanent storage location after every modification.
In your example the loop cannot be optimized as variable i can be changed during the loop (for example some interrupt routine will change it to zero so the loop will have to be executed again.
The answer to your question is: If the compiler can determine that every time you enter the loop, it will execute only once, then it can eliminate the loop.
Normally, the optimization phase unrolls the loops, based on how the iterations relate to one another, this makes your (e.g. indefinite) loop to get several times bigger, in exchange to avoid the back loops (that normally result in a bubble in the pipeline, depending on the cpu type) but not too much to lose cache hits.... so it is a bit complicate... but the earnings are huge. But if your loop executes only once, and always, is normally because the test you wrote is always true (a tautology) or always false (impossible fact) and can be eliminated, this makes the jump back unnecessary, and so, there's no loop anymore.
int blockSize = 1;
for (volatile int i=0; i<blockSize; i++)
{
foo(); // you missed a semicolon here.
}
In your case, the variable is assigned a value, that is never touched anymore, so the first thing the compiler is going to do is to replace all expressions of your variable by the literal you assigned to it. (lacking context I assume blocsize is a local automatic variable that is not changed anywhere else) Your code changes into:
for (volatile int i=0; i<1; i++)
{
foo();
}
the next is that volatile is not necessary, as its scope is the block body of the loop, where it is not used, so it can be replaced by a sequence of code like the following:
do {
foo();
} while (0);
hmmm.... this code can be replaced by this code:
foo();
The compiler analyses each data set analising the graph of dependencies between data and variables.... when a variable is not needed anymore, assigning a value to it is not necessary (if it is not used later in the program or goes out of life), so that code is eliminated. If you make your compiler to compile a for loop frrom 1 to 2^64, and then stop. and you optimize the compilation of that,, you will see you loop being trashed up and will get the false idea that your processor is capable of counting from 1 to 2^64 in less than a second.... but that is not true, 2^64 is still very big number to be counted in less than a second. And that is not a one fixed pass loop like yours.... but the data calculations done in the program are of no use, so the compiler eliminates it.
Just test the following program (in this case it is not a test of a just one pass loop, but 2^64-1 executions):
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
uint64_t low = 0UL;
uint64_t high = ~0UL;
uint64_t data = 0; // this data is updated in the loop body.
printf("counting from %lu to %lu\n", low, high);
alarm(10); /* security break after 10 seconds */
for (uint64_t i = low; i < high; i++) {
#if 0
printf("data = $lu\n", data = i ); // either here...
#else
data = i; // or here...
#endif
}
return 0;
}
(You can change the #if 0 to #if 1 to see how the optimizer doesn't eliminate the loop when you need to print the results, but you see that the program is essentially the same, except for the call to printf with the result of the assignment)
Just compile it with/without optimization:
$ cc -O0 pru.c -o pru_noopt
$ cc -O2 pru.c -o pru_optim
and then run it under time:
$ time pru_noopt
counting from 0 to 18446744073709551615
Alarm clock
real 0m10,005s
user 0m9,848s
sys 0m0,000s
while running the optimized version gives:
$ time pru_optim
counting from 0 to 18446744073709551615
real 0m0,002s
user 0m0,002s
sys 0m0,002s
(impossible, neither the best computer can count one after the other, upto that number in less than 2 milliseconds) so the loop must have gone somewhere else. You can check from the assembler code. As the updated value of data is not used after assignment, the loop body can be eliminated, so the 2^64-1 executions of it can also be eliminated.
Now add the following line after the loop:
printf("data = %lu\n", data);
You will see that then, even with the -O3 option, will get the loop untouched, because the value after all the assignments is used after the loop.
(I preferred not to show the assembler code, and remain in high level, but you can have a look at the assembler code and see the actual generated code)

Do goto statements in C and assembly break locality of reference thereby decreasing performance?

I wrote a program in C that selects random words from a book in txt file format and prints them out one by one using goto statements. When I run the program it takes about 2 to 3 minutes to start running. Could it be that goto statements break locality of reference and drastically decrease performance? Also does jmp in assembly act as goto breaking locality of reference as well?
Eventually all flow control results in some form of jump. Most only jump locally so will not break locality. If your program is taking minutes to start, you probably have it doing something like reading that (large?) text file before it does anything else. Try it with a small file and see how it runs then.
This is a very vague question. Gotos might impair locality or might not, it depends on the case. But even when this holds, it is not necessarily bad. For this case, you need to post some code. Take a look at these 2 examples:
CASE 1:
for(int i = 0; i<SIZE ; i++){
if( strcmp(words[i],"key")==0 )
goto end;
}
end:
printf("FOUND!\n");
return 1;
CASE 2:
int flag = 0;
for(int i = 0; i<SIZE ; i++){
if( strcmp(words[i],"key")==0 )
flag = 1;
}
end:
if(flag) printf("FOUND!\n");
Of course that CASE 2 enjoys more locality than the first, but CASE 1 would be more efficient (i.e. it would take less time to run), except for the case where "key" is on the last position of the array.

which is more efficient? repetitive assignment or repetitive checking

If I had a loop that checks for a specific value in an array and, for some reason, must iterate over all elements and cannot break midway.
Which of the following would be more efficient: blindly setting a flag on each match, or checking if the flag is false before setting it.
bool happened = false;
while (...) {
if (...) {
happened = true;
}
}
vs
bool happened = false;
while (...) {
if (...) {
if (!happened) happened = true;
}
}
As far as I can tell, both are more or less equivalent on the assumption that memory reads are as fast as memory writes (ignoring the extra instruction in the second example). Am I correct in my conclusions?
The compiler will make the decision for you, if you use any meaningful optimization. Write whatever is cleanest and makes sense. To me that would be the first one, since it is less code and doesn't introduce more code paths. For fun, I did some tests in Clang 3.4 -O3:
bool happened = false;
extern volatile int dontOptMe1, dontOptMe2, dontOptMe3;
while (dontOptMe1) {
if (dontOptMe2) {
happened = true;
}
}
dontOptMe3 = happened;
vs
bool happened = false;
extern volatile int dontOptMe1, dontOptMe2, dontOptMe3;
while (dontOptMe1) {
if (dontOptMe2) {
if(!happened) happened = true;
}
}
dontOptMe3 = happened;
Resulted in the following in pseudo ASM:
MOV happened, 0
BRA LOOP_END
LOOP_START:
SELECTEQ dontOptMe2, 0, happened, happened, 1
LOOP_END:
BCZC dontOptMe1, LOOP_START
EXIT:
STORE dontOptMe3, happened
vs
MOV happened, 0
BCZS dontOptMe1, EXIT
LOOP:
SELECTNE dontOptMe2, 0, R2, 1, 0
SELECTEQ happened, 0, R3, 1, 0
AND R3, R2, R3
SELECTNE R3, 0, happened, 1, 0
BCZC dontOptMe1, LOOP
EXIT:
STORE dontOptMe3, happened
The first is much more desirable. This is also a good example of how restrictive volatile types are. I was surprised the compiler couldn't transform the second into the first.
Note: SELECTXX means, if Arg1 minus Arg2 sets condition code XX, set Arg3 to Arg4, otherwise set Arg3 to Arg5. So: SELECTNE dontOptMe2, 0, R2, 1, 0 is the equivalent of: R2 = (dontOptMe2 == 0) ? 1 : 0; in C
Generally speaking, first version is more pipeline friendly, because its instruction stream is less disturbed by jump, therefore is more efficient. But it is depends on specific architecture features and compiler optimizations.
I believe the performance difference of these two versions is unnoticeable in actual situations.
Most answers so far seem to be "it depends", but I think it's pretty obvious:
If you conditionally set a value to something if it isn't that something already, it is logically identical to unconditionally setting the value. If you're lucky, the compiler will notice and treat both identically, but if it doesn't, the unconditional version wins every time.
1: It uses fewer instructions
2: The extra instructions are conditional, hurting branch prediction
If you're going with
if (cond) varx = vary;
The compiler uses one conditional branch (possibly a conditional move instead of a branch, if it is supported in the hardware)
If you're going with
if (cond && varx != vary) varx = vary;
The compiler will either simplify to the first case, or use two conditional jumps (or one jump and a conditional move).
Only profiling will tell for sure, but most likely the variable is stored in the register anyway, not in memory (unless you have many other local variables in the loop) and there will be no measurable difference at all.
Yes, you are quite correct. They are more or less the same.
To be exact, the first form might be preferrable if the "happened" happens quite often, while the second one might want to be favourable if the "happend" is quite rare. But even then, I don't think the second one is better in any way.
In the end, it is probably a micro-optimization where it is better to go for readability instead of performance.
I have run it empirically on the following code:
bool happened = false;
for (int i = 0; i < 1000000000; i++) {
if (i % 2) {
// uncomment the one you want to use
// happened = true;
// if (!happened) happened = true;
}
}
I ran it 10 times on each, getting a mean of 2.304s with standard deviation 0.013s on the first and a mean of 2.399s with standard deviation 0.007s on the second. A two-sample t-test shows that happened = true; is faster than if (!happened) happened = true; and the difference is statistically significant with with p = 7e-12.

Use a "for" or a "while" loop when only the stop condition is utilized? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why use a for loop instead of a while loop?
I am currently using embedded c. Software that i am using is keil uvision.
So i have a question regarding on which loop will u use?
Both loop does the exact same thing. As long as signal = 0, 'i' will increase by 1.
Firstly,
for(;signal==0;)
{
i++;
}
The next program:
while(signal==0)
{
i++;
}
So which loop would you use and Why? What is the difference between both of them?
Does it have any difference in terms of time taken to execute? Or it is purely based on your preference?
Generally speaking, for loops are preferred when the number of iterations is known (i.e. for each element in an array), and while loops are better for more general conditions when you don't know how many times you'll run the loop. However, a for loop can do anything a while loop can, and vice versa; it all depends on which one makes your code more readable
In this case, a while loop would be preferable, since you're waiting for signal == 0 to become false, and you don't know when that will occur.
Any for loop can be written with a while loop and vice versa. Which you do is mixture of preference, convention, and readability.
Normally, for loops are used for counting and while loops are sort of waiting for a certain condition to be met (like the end of a file). There is no performance difference.
Boilerplate for and while loops:
for(int i = 0; i < someArraysLength; i++)
{
// Modify contents of array
}
while(lineLeftInFile)
{
// Read and parse the line
}
Whichever is easiest to read and understand.
Keep in mind that someone (other than you) might at some point try to read your code.
My opinion: while
Execution time is irrelevant. Any compiler that's worth a damn will generate the exact same code.
Now, as for semantics and such...computationally,
for (init; test; increment) { /* do stuff */ }
is exactly equivalent to
init;
while (test) {
/* do stuff */
increment;
}
And without init and increment, becomes just
while (test) {
/* do stuff */
}
So computationally, the two are identical. Semantically, though, a for loop is for when you have a setup and/or increment stage (particularly if they make for a predictable number of iterations). Since you don't, stick with while.
I agree with mariusnn, whichever is easiest to read and the while would seem to be easier to read to me as well.
Looking at the assembler produced by Visual Studio 2005 when doing a Debug build, the assembler instructions look to be the same for both of these loops. And actually if you do the same loop using an if statement and a label with the true statement being to increment i and then goto the if statement again, it looks like that also generates the same assembler.
for (; signal == 0; ) {
0041139C cmp dword ptr [signal],0
004113A0 jne wmain+3Dh (4113ADh)
i++;
004113A2 mov eax,dword ptr [i]
004113A5 add eax,1
004113A8 mov dword ptr [i],eax
}
004113AB jmp wmain+2Ch (41139Ch)
while (signal == 0) {
004113AD cmp dword ptr [signal],0
004113B1 jne loop (4113BEh)
i++;
004113B3 mov eax,dword ptr [i]
004113B6 add eax,1
004113B9 mov dword ptr [i],eax
}
004113BC jmp wmain+3Dh (4113ADh)
loop: if (signal == 0) {
004113BE cmp dword ptr [signal],0
004113C2 jne loop+11h (4113CFh)
i++;
004113C4 mov eax,dword ptr [i]
004113C7 add eax,1
004113CA mov dword ptr [i],eax
goto loop;
004113CD jmp loop (4113BEh)
}
So which loop would you use and Why?
If I had to choose between the two, I would probably use the while loop, its simpler and cleaner, and it clearly conveys to other developers that the following block of code will be continuously executed until signal is updated.
then again one could do this: for(; signal == 0; i++); it seems to be the more concise, though thats assuming if indeed this will be production code.
Still all this methods seem well a bit dangerous because of overflow, even on embedded devices most clocks are still quite fast and will probably reach the upper bounds of the underlying data type quite soon, then again I don't know if this will be production code nor do I know if that is an acceptable outcome.
What is the difference between both of them?
Like you said both achieve the same goal though Im sure there other ways as I've shown or as others mentioned, the biggest difference between for and while is that one is usually use when we know the number iterations while the other we don't, though for better or worse I've seen some very unique uses of a for its quite flexible.
Does it have any difference in terms of time taken to execute? Or it is purely based on your preference?
As for performance, fundamentally its up to your compiler to decide how to interpret it, it may or may not produce the same binaries, and hence execution time, you could ask it to produce the assemblies or do some profiling.
It seems that uvision 4 IDE http://www.keil.com/product/brochures/uv4.pdf indeed does support disassembly, as noted at page 94, and profiling as noted at page 103, if that indeed is the version you are using.
Though if the difference is small enough please don't sacrifice readability just to squeeze a couple extra nano-secs, this is just my opinion, Im sure there others that would disagree.
The best advice I could give you is this, try as best as you can, to write clear code, meaning most can see what it conveys without much effort, thats efficient and maintainable.

For Loop vs While Loop

In my lecture of Design and Analysis of
Algorithms the instructor said the for loop will take less time then while loop for the following sample algo.
1. for(int i=0;i<5;i++)
{
2. print(i);
}
1. int i=0;
2. while(i<5)
{
3. print(i);
4. i++;
}
He said that the compiler will read the 1. of for while 5 times line 2. 4 times thus total time 5+4=9
But in the case of while loop. The compiler will read the 1. for 1 time,2. for 5 time, 3 for 4time and 4. for 4 time. Thus total time 1+5+4+4 = 14time
Please tell me is this right. Is for loop is faster than while loop?
Thanks.
At least with MSVC 16 (VS 2010) the code is pretty much the same in both cases:
for
; Line 5
xor esi, esi
$LL3#main:
; Line 6
push esi
push OFFSET ??_C#_03PMGGPEJJ#?$CFd?6?$AA#
call _printf
inc esi
add esp, 8
cmp esi, 5
jl SHORT $LL3#main
while
; Line 4
xor esi, esi
$LL2#main:
; Line 6
push esi
push OFFSET ??_C#_03PMGGPEJJ#?$CFd?6?$AA#
call _printf
; Line 7
inc esi
add esp, 8
cmp esi, 5
jl SHORT $LL2#main
Code in my Subversion repository.
In all the modern compilers loop analysis is done on a lower level intermediate representation (i.e., when all the high level loop constructs are expanded into labels and jumps). For a compiler both loops are absolutely equivalent.
I'll pass on performance (hint: no difference, check the generated IR or assembly for proof) however there are two important differences in syntax and maintenance.
Syntax
The scope of the i variable is different. In the for case, the i is only accessible within the for header and body, while in the while case it is available after the loop. As a general rule, it's better to have tighter scopes, less variables in-flight mean less context to worry about when coding.
Maintenance
The for loop has the neat advantage of grouping all the iterations operations close together, so they can be inspected in one shot and so checked.
Also, there is one important difference when introducing continue statements:
for(int i = 0; i != 10; ++i) {
if (array[i] == nullptr) { continue; }
// act on it
}
int i = 0;
while (i != 10) {
if (array[i] == nullptr) { continue; }
// act on it
++i;
}
In the while case, the introduction of continue has created a bug: an infinite loop, as the counter is no longer implemented.
Impact
for loops are more readable and all-around better for regular iteration patterns. Even better, in C++11 the range-for statement:
for (Item const& item : collection) {
}
where iteration is entirely taken care of by the compiler, so you are sure not to mess up! (it makes the for_each algorithm somewhat moot... and we can wish the older for form starts retreating)
By corrolary: while loops should be reserved to irregular iteration patterns, this way they will attract special care during code review and from future maintainer by highlighting the irregularity of the case.

Resources