Search

5.7 — For statements

By far, the most utilized looping statement in C++ is the for statement. The for statement (also called a for loop) is ideal when we know exactly how many times we need to iterate, because it lets us easily define, initialize, and change the value of loop variables after each iteration.

The for statement looks pretty simple in abstract:

for (init-statement; condition-expression; end-expression)
   statement

The easiest way to understand a for loop is to convert it into an equivalent while loop:

{ // note the block here
    init-statement;
    while (condition-expression)
    {
        statement;
        end-expression;
    }
} // variables defined inside the loop go out of scope here

The variables defined inside a for loop have a special kind of scope called loop scope. Variables with loop scope exist only within the loop, and are not accessible outside of it.

Evaluation of for statements

A for statement is evaluated in 3 parts:

1) The init-statement is evaluated. Typically, the init-statement consists of variable definitions and initialization. This statement is only evaluated once, when the loop is first executed.

2) The condition-expression is evaluated. If this evaluates to false, the loop terminates immediately. If this evaluates to true, the statement is executed.

3) After the statement is executed, the end-expression is evaluated. Typically, this expression is used to increment or decrement the variables declared in the init-statement. After the end-expression has been evaluated, the loop returns to step 2.

Let’s take a look at a sample for loop and discuss how it works:

First, we declare a loop variable named count, and initialize it with the value 0.

Second, count < 10 is evaluated, and since count is 0, 0 < 10 evaluates to true. Consequently, the statement executes, which prints 0.

Third, ++count is evaluated, which increments count to 1. Then the loop goes back to the second step.

Now, 1 < 10 is evaluated to true, so the loop iterates again. The statement prints 1, and count is incremented to 2.
2 < 10 evaluates to true, the statement prints 2, and count is incremented to 3. And so on.

Eventually, count is incremented to 10, 10 < 10 evaluates to false, and the loop exits.

Consequently, this program prints the result:

0 1 2 3 4 5 6 7 8 9

For loops can be hard for new programmers to read -- however, experienced programmers love them because they are a very compact way to do loops of this nature. For the sake of example, let's uncompact the above for loop by converting it into an equivalent while loop:

That doesn't look so bad, does it? Note that the outer braces are necessary here, because count goes out of scope when the loop ends.

More for loop examples

Here's an example of a for loop used to calculate an exponentiation of integers:

This function returns the value base^exponent (base to the exponent power).

This is a straightforward incrementing for loop, with count looping from 0 up to (but excluding) exponent.

If exponent is 0, the for loop will execute 0 times, and the function will return 1.
If exponent is 1, the for loop will execute 1 time, and the function will return 1 * base.
If exponent is 2, the for loop will execute 2 times, and the function will return 1 * base * base.

Although most for loops increment the loop variable by 1, we can decrement it as well:

This prints the result:

9 8 7 6 5 4 3 2 1 0

Alternately, we can change the value of our loop variable by more than 1 with each iteration:

This prints the result:

9 7 5 3 1

Off-by-one errors

One of the biggest problems that new programmers have with for loops (and other kinds of loops) is off-by-one errors. Off-by-one errors occur when the loop iterates one too many or one too few times. This generally happens because the wrong relational operator is used in the conditional-expression (eg. > instead of >=). These errors can be hard to track down because the compiler will not complain about them -- the program will run fine, but it will produce the wrong result.

When writing for loops, remember that the loop will execute as long as the conditional-expression is true. Generally it is a good idea to test your loops using known values to make sure that they work as expected. A good way to do this is to test your loop with known inputs that cause it to iterate 0, 1, and 2 times. If it works for those, it will likely work for any number of iterations.

Rule

Test your loops with known inputs that cause it to iterate 0, 1, and 2 times.

Omitted expressions

It is possible to write for loops that omit any or all of the expressions. For example, in the following example, we'll omit the init-statement and end-expression:

This for loop produces the result:

0 1 2 3 4 5 6 7 8 9

Rather than having the for loop do the initialization and incrementing, we've done it manually. We have done so purely for academic purposes in this example, but there are cases where not declaring a loop variable (because you already have one) or not incrementing it (because you're incrementing it some other way) are desired.

Although you do not see it very often, it is worth noting that the following example produces an infinite loop:

for (;;)
    statement;

The above example is equivalent to:

while (true)
    statement;

This might be a little unexpected, as you'd probably expect an omitted condition-expression to be treated as "false". However, the C++ standard explicitly (and inconsistently) defines that an omitted condition-expression in a for loop should be treated as "true".

We recommend avoiding this form of the for loop altogether and using while(true) instead.

Multiple declarations

Although for loops typically iterate over only one variable, sometimes for loops need to work with multiple variables. When this happens, the programmer can make use of the comma operator in order to assign (in the init-statement) or change (in the end-statement) the value of multiple variables:

This loop assigns values to two previously declared variables: iii to 0, and jjj to 9. It iterates iii over the range 0 to 9, and each iteration iii is incremented and jjj is decremented.

This program produces the result:

0 9
1 8
2 7
3 6
4 5
5 4
6 3
7 2
8 1
9 0

Note: More typically, we'd write the above loop as:

In this case, the comma in the init-statement is part of the variable definition syntax, not a use of the comma operator. But the effect is identical.

For loops in old code

In older versions of C++, variables defined as part of the init-statement did not get destroyed at the end of the loop. This meant that you could have something like this:

This use has been disallowed, but you may still see it in older code.

Nested for loops

Like other types of loops, for loops can be nested inside other loops. In the following example, we're nesting a for loop inside another for loop:

For each iteration of the outer loop, the inner loop runs in its entirety. Consequently, the output is:

a012
b012
c012
d012
e012

Here's some more detail on what's happening here. The outer loop runs first, and char c is initialized to 'a'. Then c <= 'e' is evaluated, which is true, so the loop body executes. Since c is set to 'a', this first prints 'a'. Next the inner loop executes entirely (which prints '0', '1', and '2'). Then a newline is printed. Now the outer loop body is finished, so the outer loop returns to the top, c is incremented to 'b', and the loop condition is re-evaluated. Since the loop condition is still true the next iteration of the outer loop begins. This prints ("b012\n"). And so on.

Conclusion

For statements are the most commonly used loop in the C++ language. Even though its syntax is typically a bit confusing to new programmers, you will see for loops so often that you will understand them in no time at all!

Quiz

1) Write a for loop that prints every even number from 0 to 20.

2) Write a function named sumTo() that takes an integer parameter named value, and returns the sum of all the numbers from 1 to value.

For example, sumTo(5) should return 15, which is 1 + 2 + 3 + 4 + 5.

Hint: Use a non-loop variable to accumulate the sum as you iterate from 1 to the input value, much like the pow() example above uses the total variable to accumulate the return value each iteration.

3) What's wrong with the following for loop?

Quiz solutions

1) Show Solution

2) Show Solution

3) Show Solution


5.8 -- Break and continue
Index
5.6 -- Do while statements

266 comments to 5.7 — For statements

  • yeokaiwei

    Is this acceptable for Quiz 2?

    [code]
    #include <iostream>

    //Wrote 2 ways, the iterative method and the equation method
    int sumTo(int value)
    {
        int i = 0;
        int j = 0;
        int k = value;
        for (i; i < value; i++)
            {
                j = j + k;
                --k;
                //std::cout << j << '\n';
            }
        return j;
    }

    // Basic equation is n(n+1)/2
    int sumEqn(int value)
    {
        return (value * value + value) / 2;
    }
    int main()
    {
        //Named input_value so users naturally associated it with "value" somewhere
        //Yet, the naming is significantly different from "value" to prevent "Ad ad" confusion
        //The part after input_ can be changed to create natural link to different functions
        //E.g. input_number, input_value, input_char.
        int input_value;
        std::cin >> input_value;
        
        std::cout<< sumTo(input_value)<<'\n';
        std::cout<< sumEqn(input_value) << '\n';
        return 0;
    }
    [\code]

    • nascardriver

      - Initialize variables with list initialization for higher type-safety
      - `i` isn't used outside of the loop. Define it in the init-statement of the for-loop to reduce its scope.
      - `k` is always `(value - i)`, you don't need `k`.
      - Use ++prefix unless you need the result. postfix++ is slower.
      - Name variables descriptively, avoid abbreviations. Time you save writing is time wasted reading.
      - `j += k` is faster than `j = j + k` for non-fundamental types.

      • yeokaiwei

        Thank you.

        I apologise for the late replies.

        I think your emails get caught up in the midst of other emails.

        I can't edit my comments anymore but I can edit the code.

  • Suyash Mallik

    Hi,
    the for-loop seems to be a very interesting thing. Where can I read in depth about them, with more examples and uses? specifically, I want to know more about what other kinds of end expressions can be used in for loops, other than increment and decrement(and other arithmetic operators)?

  • sergey

    I've played a bit with for loop end-expression statement-

    • nascardriver

      The end-expression has to be and expression. `if` and `return` are statements, not expressions. The conditional operator is an expression (It produces a value).

  • EK

    Hi! Great site guys - super helpful and fantastic of you to put in all the effort.

    I've run into something that's probably going to make me slap my forehead: I can't understand why this function returns 1...

    it seems pr goes to 0.000 once the calculation is performed.

    • EK

      I found that if I

      it works. I thought that the compiler would cast the int as double since the result is already declared as a double.

  • Andreas Krug

    Please place the "Rule: Test your loops with known inputs that cause it to iterate 0, 1, and 2 times." line in a beautiful Rule box.

  • Tom

    The given answer for question #2 does not work. I'm pretty sure it's because instead of looping, it moves straight to the return statement to complete the function. Shouldn't there be an if statement there?

  • AE35_Unit

    Moving right along. Thanks. Cheers.

    • nascardriver

      My notes to your previous submission apply. Additionally,

      If you don't know what's wrong with these, let me know and I'll tell you.

      • AE35_Unit

        for (int i{n}; i < m; ++i)
        {
            doSomething();
        }

        where n & m are real numbers.

        I understand the initialization of i, "i{0};" as I reviewed chap. 1 on, int initialization.
        I understand the difference between i++ (use, then increment) and ++i (increment, then use).
        Is there a difference in a for loop?  Almost all that I see in other places is: for (int i = 0; i < num; i++)
        So I get the: for (int i{0}; i < num; ) but was just wondering if it's better or considered better to use
        for (; ; ++i) and what, if any, is the difference.  Thanks for the help.

        I read your other info on the static int var = someNumber.  I coded some examples and totally saw how a static doesn't reset, and if called from another function could cause quite a problem if the other function expects var to be zero, thanks for that.  Take care.

        • nascardriver

          You explained the difference between `++i` and `i++` correctly.
          To make the downside of `i++` more obvious, let's say `i` is an image type and using `++` on it increases the brightness. Let's also say the image is 1GiB in size.
          `++i` increases the brightness of `i`, then returns `i`, simple.
          But what does `i++` do? It also increases the brightness, but it can't return `i`. It has to return the old value of `i`. There are 2 ways it can accomplish this. Either copy create a copy of `i`, called `temp`, then increase `i` and return `temp`. Or increase `i`, then create a copy of `i` called `temp`, decrease `temp` and return `temp`. Either way, it has to create a copy. The allocation of the memory is expensive, you'll use more ram, and the creation of the copy is expensive. `++i` doesn't need any of this.
          The same applies to any other type, just that the effect isn't as noticeable.
          The only time you should use `i++` is if you need the old value of `i`. In your loop, you're not using the returned value at all, so there's no reason to use `i++`.

  • sami

    "First, we declare a loop variable named count, and assign it the value 0."

    Shouldn't it be " First, we declare a loop variable named count, and initialize it with value 0."?

  • Raffaello

    is it preferable assigning a value or initializing variables in a for loop? and is it good practice to declare multiple variables in a for loop when it's needed?

  • Aru

    How would you loop over the characters of a string (std::string) ?

    I've found lots of ways but i would want to know which are better or which you prefer and why.

    Thanks <3.

    • Alex

      Use a ranged-for (for-each) loop:

  • Gabe

    Quiz 1

    Quiz 2

  • Simon

    Regarding question 2:
    My editor - Visual studio - complains that my return variable does not match the function type. As far as I can see, everything is int.
    Does anyone have an idea about why?

    • nascardriver

      There's nothing wrong with your code and I can't reproduce the issue. I suppose you didn't save or you're compiling a different file.

      • Simon

        Hello Nascardriver

        Thank you for the answer.
        I had saved the file, and don't think I was compiling anything else.

        Anyways, I changed the language standard from standard to explicitly be C++17 (which I though I allready had done) and the Visual studio complaint disappeared. This does not make sense to me, but if anyone else gets this problem, maybe I found a fix..

        Best regards,
        Simon

  • Sahib

    I noticed something, that the init-statement in the for loop can be initialized to 0 and 1 and would still give you the same result.

    for example:

    and

    will both print out 15

    • nascardriver

      Yes, because

      Initializing `num` to 0 adds once extra cycle to the loop that doesn't do anything.

  • Lucas

    Assignment #1:

    Assignment #2:

    Assignment #3:

    I am Brazilian, and learncpp is an extremely sensational site (even if it only supports your default language). I'm learning a lot from you, thank you.

  • JackTheHopper

    I'm starting to feel that Learncpp.com hates unsigned haha :(

  • Raul T

    My approach:
    Assignment #1:

    Assignment #2:

    Assignment #3:

    Thank you!

    • nascardriver

      Looking good :)
      Quiz 3 is unrelated to endianness. The language defines that `count` has to wrap around to it's maximum value, no matter how the integer is stored. You solutions to the problem however is correct, using a `signed` integer stops the loop.

  • notacop

    Here is my answer to question 1, I really need to figure out how the modulo operator works. I was printing odd numbers at first

    • nascardriver

      Have a look at the quiz's solution and make sure you understand it, you don't need the modules in this quiz.

      Modulus returns the remainder of a division, so you can check if it's 0 to print even numbers

  • Eric

    Here is my code for Quiz question 2).
    Is it considered a good or bad idea to name the input/variables from one function to another with the same name when they reference the same thing?

    #include <iostream>

    int getNumber()
    {
        std::cout << "Input an integer you wish to sum to:  ";
        int value{};
        std::cin >> value;
        return value;
    }

    int calcSum(int value)
    {
        int total{};
        for (int count{ 1 }; count <= value; ++count)
            total += count;
        return total;
    }

    void printTotal (int value , int total)
    {
        std::cout << "The sum of the number from 1 to " << value << " is " << total << "." << '\n';
    }

    int main()
    {
        int value{ getNumber() };
        int total{ calcSum( value) };

        printTotal( value , total );
      
        return 0;
    }

    • nascardriver

      Please use code tags when posting code.
      If two variables mean the same thing, they should have the same name. There are exceptions when a variable's name is affected by its context.

  • kavin

    Under "multiple declarations" my compiler keep showing this error if i use uniform initialization like in the example.

    error C2064: term does not evaluate to a function taking 1 arguments
    error C2064: term does not evaluate to a function taking 1 arguments

    I use VS2019. It compiles only if i use uniform or copy initialization like this,

    _________________________________________________________________________________________

    • nascardriver

      That was an error in the lesson, thanks for bringing it to our attention!
      `iii` and `jjj` already existed, so they can't be initialized anymore. We need to assign a value instead.

Leave a Comment

Put all code inside code tags: [code]your code here[/code]