About side effect of negative effect and sequence point of sequence points in C and C++

  • 2020-04-02 01:41:22
  • OfStack

I wonder if you have encountered such problems when writing code? Int I = 3; Int x = (++ I) + (++ I) + (++ I) + (++ I); What is the value of x? Do all kinds of theoretical analysis and practice on the compiler, however, it may be found that the final result is not correct, is also unstable, different compilers may produce different results. It's a headache. What is the result? For the answer to this question, in a word, Theresult is undefined! Let me take my time.

As you know, in general, the computer programs we write are executed from top to bottom, left to right. However, I'm just saying that in general, because compiler does not just translate the source code into binary code during compilation, it may also optimize the code, which may result ina change in the order of the code or the evaluation of the expression. This is a very serious problem, because when an expression has a side-effect (such as changing the value of a variable), the order in which it is executed directly affects the outcome of the program.

To ensure deterministic results for program execution, the C++ standard introduces the concept of Sequence Point, as defined by ISO/IEC:

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 seems Place.

In short, a Sequence Point is a place where all the side effects before it have occurred, all the side effects after it have not started, and all the expressions or the Sequence of code execution between the two Sequence points is undefined!

However, the C++ standard further stipulates five cases of Sequence Point:

1. At the end of a full expression
At the end of a complete expression is a Sequence Point, which means that the expression is not part of another expression. So if I have f(alpha); (g); The two statements, f() and g(), are two complete expressions, and the Side Effect of f() must occur before g().

2, After the evaluation of all function arguments in a function call and before execution of any expressions in the function body
When a function is called, after all the preparation has been done, the Sequence Point is before the function call starts. Such as calling foo (f (), g ()), foo () f, g () after the three expression which is evaluated first which is evaluated is Unspecified, but must be evaluated up to do the final function call, so the f () and g () the Side Effect occurred in what order does not necessarily, but must be in the Side Effect after all, to begin to call foo function.

After copying of a returned value and before execution of any expressions outside the function
The function is about to return a Sequence Point, because the function must end a complete expression when it returns.

4, After evaluation of the first expression in a&&b,   A | | b,   A? B: c.   The or   Type a, b,
Conditional operator? :, comma operator, logic with &&, logic, or ||, followed by Sequence Point. As conditional operator and comma operators, conditional operator expression to according to whether the value of 1 is true decide the next step for the value of the expression 2 or 3, if you decide to 2 the value of the expression, the expression of 3 will not be evaluated, on the other hand, too, the comma operator also is such, expression evaluation was over 1 continue to 2 the value of the expression.

After the initialization of each base and member in the constructor initialization list
At the end of a complete statement is the Sequence Point, which means that the statement is not part of another statement. For example, declare int a[10], b[20]; At the end of a[10] is the Sequence Point, as is at the end of b[20].

So let's go back to our problem: int x = (++ I) + (++ I) + (++ I) + (++ I); The entire statement, only one Sequence Point, also is the Point of the end of the statement, for the calculation order of the right expression without any regulation, obviously, a variety of compiler can according to the way they feel "comfortable" to calculate, this code, if only requirement on a particular platform or compiler runs, so may be brought about by the problem of poor readability, but if consider cross-platform or compiler, it is completely wrong!

Also, it is important to note that C++ does not define the assignment operator as a Sequence Point, so it says: buffer[I] = I ++; It's also undefined, because you can't make any assumptions about the order in which the expression is evaluated on the left and the right sides of the equal sign.


Related articles: