For vs. while in C programming?

149,004

Solution 1

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.

Solution 2

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);

Solution 3

For the sake of readability

Solution 4

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

Solution 5

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 ; )
Share:
149,004

Related videos on Youtube

user355546
Author by

user355546

Updated on July 05, 2022

Comments

  • user355546
    user355546 almost 2 years

    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?

    • Armstrongest
      Armstrongest almost 14 years
      You forgot the Conditional GOTO loop. While people don't think of it as a loop, I believe all loops essentially compile down to Conditional GOTO loops.
    • Nyan
      Nyan almost 14 years
      Isn't recursion also considered as loop?
    • Ciro Santilli OurBigBook.com
      Ciro Santilli OurBigBook.com about 11 years
      wouldn't it be easier to write a compiler that in x86 isa compiles a simple for loop into the more efficient loop instruction (subtraction, comparison and jump in single instruction), than one that compiles while into the loop instruction? do current compilers compile for into a loop instruction at all?
  • WhirlWind
    WhirlWind almost 14 years
    For that matter, you can also use goto as a loop.
  • WhirlWind
    WhirlWind almost 14 years
    For another matter, there's recursion. And you can replace any style of loop with any other style.
  • Rup
    Rup almost 14 years
    There's one subtle difference between for() and writing it out as a while(), though: you change the behaviour of continue. For the for() case continue executes the increment step before checking the condition whereas in the while() continue will jump straight back to the condition.
  • Armstrongest
    Armstrongest almost 14 years
    Yes, very good point. Also, I think what people forget is that when it comes down it, all loops are compiled into GOTO statements.
  • Jonathan Leffler
    Jonathan Leffler almost 14 years
    Should you discuss the behaviour of 'continue;' in a 'for' loop vs a 'while' loop? Otherwise, good answer.
  • Admin
    Admin almost 14 years
    Not really. Both for and while can execute the body zero times - a do-while cannot.
  • Armstrongest
    Armstrongest almost 14 years
    In fact... all loops are really just fancy GOTO branches.
  • Michael Mrozek
    Michael Mrozek almost 14 years
    @Neil do {if(!cond) break; /* do stuff */ } while(cond);. Ugly and repetitive, but that's kind of my point about why variations exist :)
  • Sean Edwards
    Sean Edwards almost 14 years
    +1 for excellent answer. Worth noting: for loops don't require a counter variable. In C-style languages, they are actually for (<start statement>; <continuation>; <execute after each iteration>). It just happens to be that the most common usage is counter variable: for (int x = 0 [start]; x < 100 [continue?]; ++x [post-iteration])
  • Robert Greiner
    Robert Greiner almost 14 years
    @Sean agreed, I started out just putting condition for that exact reason, but the simplest examples I could come up with involved counting. Probably because they are straightforward and easy to understand.
  • Secure
    Secure almost 14 years
    @Neil: You can use an additional flag to skip the first execution. Interchangeable says nothing about how easy or useful it is. ;)
  • clyfe
    clyfe almost 14 years
    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.
  • Sean Edwards
    Sean Edwards almost 14 years
    @WhirlWind Except that in languages without recursion you'll probably end up with stack overflows. (And you might end up here asking about stack overflows, which would make me smile a little bit.)
  • Robert Greiner
    Robert Greiner almost 14 years
    @clyfe very well said, I'm going to add this to my answer if you don't mind.
  • Michael Mrozek
    Michael Mrozek almost 14 years
    That's terribly hackish though, that's not a big reason do-while exists
  • Admin
    Admin almost 14 years
    The body of the loop is still entered - this is not the case for while and for.
  • WhirlWind
    WhirlWind almost 14 years
    @Sean yeah, I was thinking about that, and if there's a way to get around the stack overflow. Of course, if there's tail recursion...
  • Sean Edwards
    Sean Edwards almost 14 years
    @WhirlWind I remember a question on Stack Overflow asking about that. The guy was used to languages that supported tail recursion, so for some reason he just always wrote loops as recursive functions. He was confused when his C code broke. :) And the only way of recursively calling a function infinitely is to have infinite memory. If a recursive function goes that deep, the algorithm should probably be redesigned to use loops instead.
  • Michael Mrozek
    Michael Mrozek almost 14 years
    @Neil Well, for certain definitions of "body of the loop". It causes the same behavior either way -- it doesn't run the /* do stuff */ part if cond is false
  • Samvel Aleqsanyan
    Samvel Aleqsanyan almost 14 years
    nop, i never said that, but that's one usage really particular for do-while, which is pretty pervasive.
  • JYelton
    JYelton almost 14 years
    +1 well-written answer, and sometimes revisiting the "basics" is good for everyone
  • Shravan
    Shravan almost 14 years
    I love the answer, esplly the part where you talk about uniformity in incrementing the counter in case of a 'for' versus potentially anywhere in the iteration in case of a 'while'. To be honest, I would have never put it so eloquently albeit there is not much new here
  • Judge Maygarden
    Judge Maygarden almost 14 years
    Also, a switch statement can be implemented more efficiently than a series of if-statements in many cases (see stackoverflow.com/questions/449273).
  • Michael Mathews
    Michael Mathews almost 14 years
    This is a good answer. One situation where it may be less obvious which type of loop to use is when using iterators. You don't know how many times the loop will execute, but for loops can be pretty concise ways of processing a list. std::list<int> foo_list; std::list<int>::const_iterator iter; for (iter = foo_list.begin(); iter != foo_list.end(); ++iter) { int a = *iter; if (a % 2) { std::cout << "The number is odd" << std::endl; } }
  • Michael Mathews
    Michael Mathews almost 14 years
    I think this is why while loops more often lead to infinite loop bugs -- the increment step can be skipped by a continue somewhere.
  • Callum Rogers
    Callum Rogers almost 14 years
    I actually learnt that there is a continue keyword. To think some people tried to close this question!
  • Bob
    Bob almost 14 years
    specifically in C, FOR loops do not have to use a counter, but it other languages like pascal they do. C uses a more flexible FOR loop structure than other languages, in C one (or more) parts of the FOR expression can even be left blank, and conditions can be more complex or simple, something that's not always possible in other languages, for example you can do: for (; (i<4) && (j>5); i++) or even: for (;;). just thought it might be worth mentioning.
  • caf
    caf almost 14 years
    It is true though that while (x) could be replaced with for (;x;) - I suppose the former is just a bit nicer to look at.
  • caf
    caf almost 14 years
    I don't know about much easier. I would hazard a guess that if C didn't have the first form, we would all be quite used to seeing the second by now.
  • Justin Ethier
    Justin Ethier almost 14 years
    Fair enough, but I guarantee I would be thinking "WTF" if I saw the second version in any code I was maintaining...
  • Armstrongest
    Armstrongest almost 14 years
    @Michael: Yep, very true. for loops were probably introduced as convenience and productive methods.
  • Armstrongest
    Armstrongest almost 14 years
    53 upvotes for a while loop question!!! Why can't answers to really difficult questions get this much!
  • JeremyP
    JeremyP almost 14 years
    @Rup A very good point. I've always regarded for as syntactic sugar for while, but the continue behaviour means it is not true.
  • JeremyP
    JeremyP almost 14 years
    @Michael yeah it's a hack but it is a really commonly used one that makes a macro containing multiple statements behave completely as expected in all syntactic contexts.
  • JeremyP
    JeremyP almost 14 years
    "For loops are simply syntactically sugared while loops": as has already been pointed out in one of the comments above, this is not strictly correct. A continue inside a for does not bypass the loop expression (e.g. the i++ in for (i = 0 i < limit ; i++).
  • Michael Mrozek
    Michael Mrozek almost 14 years
    @JeremyP I know, I use it too, but it's not a real use-case for do-while, it's just used because it happens to create a block and still require a semi-colon at the end
  • Samvel Aleqsanyan
    Samvel Aleqsanyan almost 14 years
    i just wanted to point this particular usage of do-while. Part of the question was, what are the differences... and that's one difference. (but i agree, that's hackish)
  • Avio
    Avio over 11 years
    There are consistent differences between while, do while and for loops. Take a look at the top answer and you'll find them.
  • Amal Murali
    Amal Murali over 10 years
    Very well written answer. Nicely explained. +1.
  • FredCooke
    FredCooke about 10 years
    Code should read as prose, the former is much closer to natural language. Perhaps not "much easier" but quite likely much faster to recognise and comprehend.
  • klutt
    klutt over 6 years
    If the for header becomes to long, just split the line after a semicolon. This is not an argument for while instead of for.
  • Jay
    Jay over 6 years
    @klutt The problem with a long and involved expression involving nested ternary operators and six levels of parentheses or some comparable complexity is not per se that the line is too long to fit in the editor window, but that it becomes difficult to read and understand.
  • klutt
    klutt over 6 years
    True, but that has nothing to do with which kind of loop you choose.
  • Jay
    Jay over 6 years
    @klutt Sure it does. If the "next" operation involves complex logic with many conditions, it cannot be readily place in a FOR loop. You'd have to either have a complex expression with nested ternaries or some such, or you'd have to take the next out of the FOR statement and put it in the body of the loop. At which point, you may as well write a WHILE loop.
  • David A. Gray
    David A. Gray about 6 years
    A SWITCH statement that tests all of a set of contiguous integral values is vastly more efficient than a set of IF statements. because any decent optimizing compiler generates a jump table, giving it the blazing efficiency of the computed GoTo of the ancient FORTRAN programming language. For example, the Microsoft Visual C++ compiler generates such jump tables, even in DEBUG mode, and going at least back to VC++ 6.0/
  • Will
    Will over 4 years
    For completeness' sake, the last sentence of this answer should read "in contrast, in a while loop or do/while loop, it just jumps to re-evaluate the loop condition". (I tried to edit it directly myself, but a few boneheaded reviewers rejected the edit.)