Search

Admin

3.3 — Increment/decrement operators, and side effects

Incrementing (adding 1 to) and decrementing (subtracting 1 from) a variable are so common that they have their own operators in C. There are actually two version of each operator -- a prefix version and a postfix version.

Operator Symbol Form Operation
Prefix increment (pre-increment) ++ ++x Increment x, then evaluate x
Prefix decrement (pre-decrement) –– ––x Decrement x, then evaluate x
Postfix increment (post-increment) ++ x++ Evaluate x, then increment x
Postfix decrement (post-decrement) –– x–– Evaluate x, then decrement x

The prefix increment/decrement operators are very straightforward. The value of x is incremented or decremented, and then x is evaluated. For example:

The postfix increment/decrement operators are a little more tricky. The compiler makes a temporary copy of x, increments or decrements the original x (not the copy), and then evaluates the temporary copy of x. The temporary copy of x is then discarded.

Let’s examine how this last line works in more detail. First, the compiler makes a temporary copy of x that starts with the same value as x (5). Then it increments the original x from 5 to 6. Then the compiler evaluates the temporary copy, which evaluates to 5, and assigns that value to y. Then the temporary copy is discarded.

Consequently, y ends up with the value of 5, and x ends up with the value 6.

Here is another example showing the difference between the prefix and postfix versions:

This produces the output:

5 5
6 4
6 4
6 4
7 3

On the third line, x and y are incremented/decremented before they are evaluated, so their new values are printed by cout. On the fifth line, a temporary copy of the original values (x=6, y=4) is sent to cout, and then the original x and y are incremented. That is why the changes from the postfix operators don’t show up until the next line.

Side effects

A side effect is a result of an operator, expression, statement, or function that persists even after the operator, expression, statement, or function has finished being evaluated.

Side effects can be useful:

The assignment operator has the side effect of changing the value of x permanently. Even after the statement has finished executing, x will have the value 5.

Side effects can also be dangerous:

C++ does not define the order in which function parameters are evaluated. If the left parameter is evaluated first, this becomes a call to add(5, 6), which equals 11. If the right parameter is evaluated first, this becomes a call to add(6, 6), which equals 12! Note that this is only a problem because one of the parameters to x has a side effect.

There are other cases where C++ does not specify the order in which certain things are evaluated, so different compilers will make different assumptions. Even when C++ does make it clear how things should be evaluated, some compilers implement behaviors involving variables with side-effects incorrectly. These problems can generally all be avoided by ensuring that any any variable that has a side-effect applied is used no more than once in a given statement.

Rule: Don’t use a variable that has a side effect applied to it more than once in a given statement.
Rule: Favor pre-increment and pre-decrement over post-increment and post-decrement. The prefix versions are not only more performant, you’re less likely to run into strange issues with them.

3.4 -- Sizeof, comma, and conditional operators
Index
3.2 -- Arithmetic operators

38 comments to 3.3 — Increment/decrement operators, and side effects

  • som shekhar

    you have written the statement for the post fix increment as;

    The postfix increment/decrement operators are a little more tricky.
    The compiler makes a temporary copy of x, increments x,
    and then evaluates the temporary copy of x.

    but compiler should first evaluate the temporary copy of x and then it should increment x.
    please correct me if i am wrong!!

    thanks
    Som Shekhar

    • I believe what I wrote is correct. If you find something that seems to indicate otherwise, let me know.

      • I don’t know the internals of the C++ compilers, but I can see how this is confusing. May I suggest that unless you know the compiler actually does it in that order that you change it to:

        The compiler makes a temporary copy of x, evaluates the temporary copy of x, and then increments x.

        As this will make it clearer that that the increment of x does not affect the copy of x. If I’m not mistaken mr Shekhar understood the copy as a pointer like thing, whereas I assume you meant a complete clone of the memory for x.

        Another suggestion, what about motivating people to use the debugger for code like this? This seems like the perfect place to get some simple and safe experience, where the debugger may make it more clear what actually happens. I guess the challenge here is what debuggers people will use though :/ but yeah just a thought :)

  • kULDEEP

    CAN YOU EXPLAIN THE BELOW ASSIGMENT OPERATOR, PLEASE:

    INT SUM, CTR;
    SUM=12;
    CTR=4;
    SUM = SUM + (++CTR)

    THE VALUE IS 15 …..HOW?

    SUM = SUM + (-CTR)

    THE VALUE IS 15 …..HOW?

    SUM = SUM + (CTR++)
    THE VALUE IS 16 …..HOW?

    SUM = SUM + (CTR-)
    THE VALUE IS 16 …..HOW?

    thanx in advance

    • Peter P

      Tried to evaluate the first expression and I get the expected result SUM = 17.

      Have not tried the other exampels but assume I will get the expected results as well. No idea how you end up with your results?!

    • csvan

      At face value this looks strange…I will go over them in order.

      1. This one should evaluate to 17, like Peter P said. There is no way it can evaluate to 15, since it will become: (SUM = 12 + 5).

      2. again, something is wrong. This one should be (I think), SUM = 12 + (-4) = 8.

      3. This one should be correct, as the postfix ++ will increment CTR AFTER the expression is evaluated (I think).

      4. I have never seen a single - postfixed like this, I dont believe it should even compile.

      Use your compiler to try and compile each statement, and see what happens. I have just written my observations here, I did not compile the code.

  • Danny

    It says above that… “C++ does not define the order in which function parameters are evaluated.”
    But in the section “Precedence and associativity” it shows that () “Parenthesis”, () “Function calls”, () “Implicit assignments”, and , “comma” have an associative of left to right… what is the difference?

    • Dogbiscuit

      No, what he said is that function parameters could be done left to right, or right to left. E.g.

      It’s not defined whether you do a + b or b + a (makes no difference in this case, but with increment/decrement operators it could get messy.

    • Alex

      I can see how this would be confusing. The comma used inside a function call parameter list to separate the parameters isn’t the comma operator. So while the comma operator does have a left to right association, the order that parameters inside a function call are processed could be either direction.

  • moncef

    hi Alex!

    I tried to test the precedence of the ++ operator, both prefix and postfix.
    The code i typed in is:

    Why the is ++x++ illicit?
    Thanks for the nice tutorial.

    • Alex

      ++x++ evaluates as ++(x++) due to post-increment having a higher precedence than pre-increment.

      Note that both versions of ++ need to operate on an lvalue (a variable that has an address). With pre-increment, because the increment is done before the value is evaluated, the value is returned as an lvalue. However, with post-increment, the value gets evaluated before the increment, so the value is returned as an rvalue.

      So in your expression, x++ is returning an rvalue, and pre-increment can’t work with an rvalue, so the compiler throws an error.

      Note that if you write the expression as (++x)++, then it does work, because (++x) returns an lvalue that can be operated on by post-increment.

  • oh no . complecated. need to learn easiest way.

  • smitha

    Hi, I teach C++ to 12th graders. I encountered this problem in the lab wherein the statement

    I would expect the value 13, but my students got 14 as the output. any pointers?
    what is funny is that the following code gives the value 13.

    The only difference being in the way x is initialized. I am baffled!!!

    • pravin

      answer to the second code snippet is also = 14

    • X000X

      Remember that operator precedence requires that ++ be evaluated before + and =. So what happens is ++y is evaluated twice with y becoming 6 then 7. The addition 7+7 is then performed before finally assigning result 14 to x.

    • Kush

      I fear I also got two different answers, using Turbo c IDE.

      Now, the answer might lie in Order of precedence, though i cannot satisfactorily expalin it.

      Here, acc to table Alex gave:

      Pre-increment and Dynamic initialization fell in third box, with evalauation going Right to left.
      Therefore in second scenario, the case might be:
      (Going Left to Right)

      int x ( This evaluates third, giving x=13) = ++y(This evalautes second, giving y=7) + ++y (This evaluates first, giving y=6);

      IN first case, no dyanmic initialization, and hence, x is evaluated pretty much same way.
      x = ++y + ++y;
      Both ++y having higher precedence, than any other operand in statement are evaluated to 7 apeice, giving answer 14.

      Though, I think this can explain it, I would like to have confirmation…. I will post it out on forums sometime… and see if anyone agrees with me, or provides better explanation.

    • technocrat

      Hello buddy, dont panic, your students r right ,try to understand this-
      int y=5,x;
      x=(++y)+(++y);// x=6+7=13 but when compiler encounter 1st expresion ++y it increment value of y to 6 now y is 6 nd when it encounter another ++y in statement ++y, value of y becomes 7 now notice that compiler now have or assign value of y to 7, now compiler treats all occurence of y value to 7 in statement before assining value to x,so whether it is
      x=(++y)+(++y);
      x=6+7;//incremented or say highest value of y becomes value of y for compiler before assigning to x nd therefore expression becomes
      x=7+7;
      x=14;
      or consider another ex. for better understanding
      x=(++y)+(++y)+(++y);
      x=6+7+8;//incremented or highest value of y will become value of y before assining to x so it becomes-
      x=8+8+8;
      x=32; hope that u can understand now,thanks.

    • It’s as technorat said.
      consider this expression: x = (a++) + (a++);
      now what happens is it takes the value of a, adds the value of a to it, and then does the incrementing (if a = 5, then x will be 10, and a will be 7 in the end).
      It’s the same thing when having ++ in front.
      example x = (++a) + (++a);
      It takes a value, increments it, then it sees another ++ in the statement, so it increments ‘a’ again, and then it does the adding, meaning that if a was 5, then x will be 14, and a will be 7 in the end.
      Also - you don’t really need the brackets in this case, as ++ has higher priority than the standard + sign (tho it helps the readability).

  • nagaraj

    Hi all
    int i=2;
    i=++i * i++ * i++; answer i am geeting is 29
    n=++i+i++*i++; answer i am getting is 27
    printf(“%d”,++i+i++*i++); answer i am getting is 36

    how complier is going evalute? please reply me…

  • nagaraj

    Hi all
    int i=2;
    i=++i * i++ * i++; answer i am geeting is 29
    n=++i*i++*i++; answer i am getting is 27
    printf(“%d”,++i*i++*i++); answer i am getting is 36
    for same expression getting different values..please sort this problem

    how complier is going evalute? please reply me…

    • printf for some reason seems to evaluate the i++ once it’s done, so it’s 3 (you incremented it before using it - ++i) * 3 * 4.
      the second case (n=) simply evaluates the i++, and since the other additions are done only after the statement is done, you get 3*3*3
      the first case is the same as the second one, except it adds +2 gained from the increments (i++) before.

  • INNOVISION

    int t;
    t= ++t + ++t + t++ + t++;
    printf(“%d”,t);
    //result=14 how??

  • Ramadharkumar

    hey, this code give the output 14.
    int t=1;
    t=++t + ++t + t++ + t++;
    that is
    t=2+3 and in postincrement operator 3+4;
    t=2+3 + 3+4;
    t=3+3 + 4+4;
    t=6 +8;
    t=14;
    if the number of preincrement is greater than post then value of post operator is bigest value of preincrement operator;
    for example:
    t=1;
    t=++t + ++t + ++t + t++ + t++;
    output is 20; BECAUSE
    t=2+3+4 + 4+4;
    t=4+4+4 + 4+4;
    t=20;

    • ahleyn

      it’s really confusing.how come t=3+3+4+4?

      • Paperweight

        Given
        int t = 1;
        Since
        cout << ++t + ++t + t++ + t++;
        outputs 12 (as in 3 + 3 + 3 + 3), but
        t = ++t + ++t + t++ + t++;
        cout << t;

        outputs 14, I think what happens is:
        1. t is declared to be 1.
        1. t is preincremented. t is now 2.
        2. t is preincremented. t is now 3.
        3. t = t + t + t + t is evaluated. from 3 + 3 + 3 + 3, t is now 12.
        4. t is postincremented. t is now 13.
        5. t is postincremented. t is now 14.
        6. t is printed.

        • Paperweight

          Actually I’m probably wrong.

          //But wait! There's more!

          int t = 1;
          cout << t++ + t++ + t++ + t++ << endl;
          cout << t << endl << endl;
          // Should evaluate 1 + 1 + 1 + 1 as 4,
          // then output 4,
          // then increment t four times to 5,
          // then output t as 5.
          // Actually outputs 4 and 5 OK.

          t = 1;
          t = t++ + t++ + t++ + t++;
          cout << t << endl << endl;
          // Should evaluate 1 + 1 + 1 + 1 as 4,
          // then set t to 4,
          // then increment t four times to 8,
          // then output t as 8.
          // Actually outputs 8 OK.

          t = 1;
          cout << ++t + ++t + ++t + ++t << endl;
          cout << t << endl << endl;
          // Should increment t four times to 5,
          // then evaluate 5 + 5 + 5 + 5 as 20,
          // then output 20,
          // then output t as 5.
          // Actually outputs 15 and 5 WTF?

          t = 1;
          t = ++t + ++t + ++t + ++t;
          cout << t << endl;
          // Should increment t four times to 5,
          // then evaluate 5 + 5 + 5 + 5 as 20,
          // then set t to 20,
          // then output t as 20.
          // Actually outputs 15 WTF?

          • Alex

            Seems like your compiler may not be doing something quite correctly.

            Should evaluate as 20 and 5, and it does in Visual Studio 2008.

            That’s one of the many problems with including multiple expressions with side effects in a single statement. Even if the C++ language guarantees that it will evaluate a certain way (and it may not), your compiler may not do it correctly.

  • zhiwei

    Hi ,Alex,  I am confused . because " ++ " is higher precedence than " = "

    so I think first x++ ,and then y = (x++),  so y is 6 .

    please correct me if i am wrong!! Thanks.

    • Alex

      Great question, and yes, you are wrong. :)

      As you correctly note, ++ has higher precedence than =, so x++ evaluates first. What happens when x++ evaluates? The compiler makes a temporary copy of x’s value (5). Then the actual variable x is incremented to 6. Then the value of the copy of x (5) is used for evaluation. Therefore, x++ evaluates to 5, now 6, even though the variable x is now set to 6!

      And thus, “int y = x++” becomes “int y = 5″, and thus y is assigned the value of 5.

      You can validate that this is true by putting this line in your compiler and then printing the value of x and y afterward.

  • techsavvy....aye

    Hi! Alex.
    The program u have given above is displaying a blank o/p what could be the possible problem?
    please help!

    • Alex

      This program doesn’t print anything, so there’s no output.

      I updated the sample program to print value, so you can see whether it equals 11 or 12 on your compiler.

  • techsavvy....aye

    Thanks,Alex.

  • am

    Can anyone explain why the output is 11 9 11?

    • Alex

      Honestly, I’m not sure.

      operator<< evaluates from left to right, so I’d expect the following to happen: a = 10 ++a = 11, which gets printed. a++ means 11 gets printed, a is incremented to 12. -a = 11, which gets printed. So I’d expect 11 11 11. But Visual Studio 2010 and 2013 prints 11 9 11. Visual Studio 2008 prints 10 9 11. So even different compilers don’t agree. It’s possible that the compilers just aren’t handling this case correctly. Which would be more evidence not to use a variable that has a side effect applied to it more than once in a given expression.

  • Hey Alex! something is wrong. I am unable to write xminusminus (post decrement of a variable ‘x’). When I type xminusminus and looking back to my posted comment, I only see a single minus after x (something like ‘x-‘). That is not a big problem and you can ignore this . I am only trying to clear that you made a mistake in the table above. Sorry for this extra comment.

    It is okay when I use [code] tag.

    Take a look at the last row of the table (the table which is showing the two versions of increment-decrement operators) :

    "Postfix decrement (pre-decrement)" |   --   |  x-  | Evaluate x, then decrement x

    should be:

    "Postfix decrement (post-decrement)" |  --  |  x-  |  Evaluate x, then decrement x

    One question. I m not very good in math. Can I still be a good programmer? How math is related to programming?

    • Alex

      What browser are you using? It looks okay to me on Chrome, Firefox, and IE.

      As for programming and math, it depends on what kind of programming you want to do. If you’re going to do complicated stuff with algorithms, 3d graphics, probability, or simulations, then yes, having a good math background is important. If you’re going to do business programming, or functionality for web pages, or user interfaces, then you probably won’t need much math.

      What’s more important is being good at logic.

      • I m using chrome. Thnx.
        Looks like you didn’t noticed what I said.   Alex I was talking about the table (post decrement, pre decrement table). You made a typo I think, in the last row of table.

        Postfix-decrement (pre-decrement)

        Should be:

        Postfix-decrement (post-decrement)

        Hope it is clear now.

Leave a Comment

  

  

  

nineteen + four =

Put C++ code inside [code][/code] tags to use the syntax highlighter