In C, side effect refers to the modification of data objects or files. For example, the following statement var = 99;
The side effect is to change the var value to 99. Evaluate the expression may also produce side effects, such:
Se = 1, 100
The side effect of this expression is that the se value is modified to 100.
Sequence point refers to a special time point in the program running. All the side effects before this point have ended, and subsequent side effects have not yet occurred.
The end mark of the C statement-semicolon (;) is a sequence point. That is to say, the side effects caused by the assignment, auto-increment, or auto-subtraction in the C statement must end before the semicolon. We will talk about some operators that contain sequence points in the future. The time point at which any full expression operation ends is also a sequence point. The complete expression is not a subexpression. The so-called subexpression refers to the expression in the expression. For example:
F = ++ e % 3
The entire expression is a complete expression. In this expression, ++ e, 3, and ++ e % 3 are all its subexpressions.
With the concept of sequence points, we will analyze a common error:
Int x = 1, y;
Y = x ++;
Here, y = x ++ is a complete expression, and x ++ is its subexpression. The end of this complete expression operation is a sequence point, where int x = 1, y; is also a sequence point. That is to say, x ++ is located between two sequence points. The standard stipulates that the value saved by an object can be modified only once between two sequence points. But we can see clearly that in the above example, the value of x is modified twice between two sequence points. This is obviously wrong! Compiling this code on different compilers may lead to different values of y. The common result is that the value of y is changed to 2 or 3. Here, I am not going to make a more in-depth analysis on this issue. You only need to remember that this is wrong and you can simply stop using it. If you are interested, you can refer to the relevant information listed below.
The C language standard defines side effects and sequence points as follows:
Accessing a volatile object, modifying an object, modifying a file, or calling a function that does any of those operations are all side effects, which are changes in the state of the execution environment. evaluation of an expression may produce side effects. 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.
Translation:
Accessing variable objects, modifying objects or files, or calling functions that contain these operations are all side effects and change the status of the execution environment. Computing expressions can also cause side effects. Some specific points in the execution sequence are called sequence points. At the sequence point, the side effects of all operations before this point should end, and the side effects of subsequent operations have not yet occurred.
Bytes ----------------------------------------------------------------------------------------------
Let's take a look at the following code:
Int I = 7; printf ("% d \ n", I ++ * I ++ );
What do you think will be returned? 56? No. The correct answer is 49? Many may ask why? Shouldn't 56 be printed? Ccfaq has a very detailed explanation, the root cause is the sequence point in c.
Note that although the suffix auto-increment and suffix auto-subtraction operators ++ and-are not executed until their old values are output, the "post" here is often misunderstood. There is no guarantee that auto-increment or auto-increment will be performed immediately after the original value of the output variable and before the rest of the expression is calculated. It cannot be guaranteed that the update of the variable will be performed at a certain time before the expression is completed (according to ansi c, before the next "sequence point. In this example, the compiler chooses to multiply the old value of the variable before auto-incrementing the two. Only after reaching a sequence point can the auto-increment operation be truly executed.
The behavior of code containing multiple uncertain side effects is always considered undefined. (In short, "multiple uncertain side effects" refers to the auto-increment that is referenced after being modified twice or modified for the same object in the same expression, any combination of subtraction and value assignment operators. This is a rough definition .) Do not even try to explore how these things are implemented in your Compiler (this is the opposite of the mental exercises in many C textbooks); As K & R wisely pointed out, "If you don't know how they are implemented on different machines, this ignorance may help protect you ".
So what does the so-called sequence point mean?
A sequence point is a time point (after the entire expression is fully calculated or after | ,&&,? : Or a comma operator, or before a function call), the dust is settled at this moment, and all side effects are ensured to end. The ANSI/iso c standard is described as follows:
The value saved by an object between the previous and next sequence points can only be modified once by the calculation of the expression. The previous value can only be used to determine the value to be saved.
The second sentence is confusing. It means that if an object needs to be written in an expression, access to the object in the same expression should be limited to directly used to calculate the value to be written. This rule effectively limits the validity of expressions that can only access variables before modification.
For example, I = I + 1 is valid, while a [I] = I ++ is invalid. Why is this code: a [I] = I ++; cannot work? The subexpression I ++ has a side effect-it will change the value of I-because I is referenced elsewhere in the same expression, this will lead to undefined results, there is no way to determine whether the reference (in a [I] on the left) is an old value or a new value. So, for a [I] = I ++; we don't know which component of a [] will be rewritten, But I does increase by 1, right?
Not necessarily! If an expression and program become undefined, all its aspects become undefined.
Why can the & | Operator generate sequence points? These operators have a special exception here: if the left-side subexpression determines the final result (that is, true for | and false for &), the right-side subexpression will not be calculated. Therefore, the calculation from left to right ensures that the same is true for comma expressions. And all these operators (including? :) Will introduce an additional internal sequence point.