83 lines
1.9 KiB
Plaintext
83 lines
1.9 KiB
Plaintext
== Why is this an issue?
|
|
|
|
A sequence point is the still point of calm between evaluations; all the side effects of the previous operation have been calculated, and the next operation has not yet started.
|
|
|
|
|
|
There is no sequence point between the arguments to a function call, so function calls with multiple arguments that produce side effects result in undefined behavior. I.E. it's up to the compiler to pick an order in which to execute the statements, potentially resulting in unexpected runtime results.
|
|
|
|
|
|
Specifically, the use of increment and decrement operators in function calls can result in undefined behavior because there is no sequence point in the operation. Even if there were, such code would still be difficult to understand.
|
|
|
|
|
|
Similarly, passing function calls as arguments to function calls can also result in undefined behavior.
|
|
|
|
|
|
This is also true for expression where one variable is present more than once and is modified by a postfix, or prefix operator ``{plus}{plus},--``.
|
|
|
|
|
|
=== Noncompliant code example
|
|
|
|
[source,text]
|
|
----
|
|
int counter;
|
|
|
|
void f(int i) {
|
|
|
|
a[i++] = i; // Noncompliant; the value that will be assigned is unspecified
|
|
|
|
int c = i + a[++i]; // Noncompliant; 'i' is evaluated more than once.
|
|
|
|
g(i++, i); // Noncompliant. What value(s) will be passed to g?
|
|
|
|
g(counterSet(), counter++); // Noncompliant; same var modified twice but order undefined
|
|
|
|
g(counterSet(); counterInc()); // Noncompliant; both fcns modify same var. Evaluation order undefined
|
|
}
|
|
|
|
void g(int i, int j) {
|
|
//...
|
|
}
|
|
|
|
void counterSet() {
|
|
counter = 0;
|
|
}
|
|
|
|
void counterInc() {
|
|
counter ++;
|
|
}
|
|
----
|
|
|
|
|
|
=== Compliant solution
|
|
|
|
[source,text]
|
|
----
|
|
void f(int i) {
|
|
int tmp = i+1;
|
|
int c = i + a[tmp];
|
|
|
|
a[tmp] = i;
|
|
g(tmp, i);
|
|
|
|
counterSet();
|
|
int count1 = counter;
|
|
counterInc();
|
|
int count2 = counter;
|
|
g(count1, count2);
|
|
}
|
|
|
|
void g(int i, int j) {
|
|
//...
|
|
}
|
|
|
|
void counterSet() {
|
|
counter = 0;
|
|
}
|
|
|
|
void counterInc() {
|
|
counter ++;
|
|
}
|
|
----
|
|
|
|
|