Pre and post increment operators c ++

-4

Who explains the behavior of this, please:

unsigned int q = 0;
cout << q++ << " " << q++ << endl;
cout << q << " " << q++ << endl;
cout << q++ << " " << q << endl;
cout << ++(q += ++q) << " " << ++ ++q << endl;
    
asked by danquin 31.01.2018 в 19:48
source

2 answers

6

There is not much to explain ... each one will give a different result.

The first line can be 00 , 01 , 10 , ... and something similar to the following and this is so because C ++ focused on performance and, consequently, leaves a lot of room for maneuver to compilers when optimizing certain sets of instructions.

Effectively in C ++, q++ is an instruction with a postincremento , so if we do this:

int q=0;
std::cout << q++;
std::cout << q++;

We see that the sequence 01 is actually printed ... however, the instruction std::cout << q++ << q++; gives an indeterminate result why?

Basically because the standard clearly indicates that in a post-increment the variable is first evaluated and then the increase ... but it says absolutely nothing about when that increment must be executed ... well yes, it says one thing and that is must be executed before the next sequence point ...

In this case the sequence points are established at the end of each instruction (the semicolon), then the post-increments can be executed at any time between the evaluation of the variable and the end of the instruction.

On the other hand ... it could not be otherwise, the order in which the variables are evaluated is indeterminate, so the first line of your code could end up being one of these cases:

Case 1: postincrements at the end

std::cout << q;
std::cout << q;
++q;
++q;

Case 2: evaluation from left to right

std::cout << q;
++q;
std::cout << q;
++q;

Case 3: evaluation from right to left

int temp = q;
++q;
std::cout << q;
std::cout << temp;
++q;

And with the rest of the instructions more of the same ... so you know, do not do this kind of thing in the code because the result will be unpredictable.

Some additional clarifications:

versions before C ++ 11

In these versions the sequence points are defined such that:

  

At certain specified points in the execution sequence called sequence points, all side effects of previous evaluations shall be complete and no side effects of subsequent evaluations shall have taken place. (§1.9 / 7)

What comes to say the following:

  

A sequence point is a specific point in the execution in which the side effects of the previous evaluations must be complete. Evaluations after this point will have no effect on the previous evaluations.

As you can see it refers to side effects ... What is this?

Side effects are changes that occur in the state of the application (that is, variables that change their value) and that may affect the execution result. As an example, use the first line of the question code:

cout << q++ << " " << q++ << endl;

Here are two side effects that are the two increments of q . They are side effects because it is not specified at what specific moment they should be executed. We only know that there are operations that will have been executed yes or yes upon reaching the semicolon that delimits the line of code.

What sequence points can we find?

  • Logical operators:
    • A && B
    • A || B
  • if ternary: A ? B : C
  • operator comma: A , B .

    Not applicable when the comma acts as a separator , for example in function calls: func(A,B)

  • In function calls, after evaluating all the arguments of the call.

For giving some examples of non-indefinite behavior :

int a = 0;
bool b = a++ || a++; // a = 2
b = a++ || a++;      // a = 3 <--- la expresión sufre cortocircuito
b = a++ && a++;      // a = 5
a++, a++;            // a = 7
a++ ? a++ : a=0;     // a = 9

Undefined Behaviors :

int a=0;
int b = a++ + a++;
func(a++,a++);
b = (a++ + a++) + a++;

C ++ 11 and up

In C ++ 11 the concept of sequence point disappears. Its scope is divided into three different elements to better identify each behavior although the behavior is exactly the same:

  • sequenced before
  • not sequenced
  • indeterminate sequence
answered by 31.01.2018 в 20:05
2

Adding little ... Here I explain the behavior I got from your code.

The increase operator ++ in both C and C ++ act as follows (I assume you already know) :

  • Pre-increment: Increase the value of the variable before using it.
  • Post-increment: Increase the value of the variable AFTER having returned its value previously.

For what we have:

unsigned q = 0;
cout << q++ << endl;
cout << ++q << endl;

Will print:

0
2

At the moment of printing the q++ , the operator ++ is responsible for returning the value of q and then increasing its value, so you never see the 1 on the screen, when it is time to make ++q , first it is increased and then it shows on the screen the value of 2.

Applied to your code, it could be said that (...) :

  • Prints the value of q , then increases its value (which is now 1) , prints again the value of q and finally, increases its value; in this example, q has the value of 2 at the end:

    cout << q++ << " " << q++ << endl;
    
  • Print the value of q (If we follow the sequence, it is 2) , then print again its value (2) and then increase the variable (So that its value is 3 now) :

    cout << q << " " << q++ << endl;
    
  • Print again the value of q and increase so that its value is 4 and then print its value:

    cout << q++ << " " << q << endl;
    
  • Finally: What you do here is beautifully horrifying (IMHO) , first pre-increase the value of q to add it and assign it to q , which is then increased, leading to a: ++(4 += ++4) that would be simplified to: ++(5 += 5) and finally ++(10) , after printing this value (In my case 11) , ++ ++q is executed evaluating ++ ++11 -> ++ 12 -> 13 :

    cout << ++(q += ++q) << " " << ++ ++q << endl;
    

This has been the result that the ideone has thrown at me and is how it mentions eferion in your answer, all this is totally dependent on compiler the fact of applying these optimizations, even of platform.

You can try with printf of cstdio and you will see a totally different result.

    
answered by 31.01.2018 в 20:17