...
These examples are independent of the order of evaluation of the operands and can be interpreted in only one way.:
Code Block | ||||
---|---|---|---|---|
| ||||
void f(int i, const int *b) { ++i; int a = i + b[i]; // ... } |
...
The first (left) argument expression reads the value of i
(to determine the value to be stored) and then modifies i
. The second (right) argument expression reads the value of i
, but not to determine the value to be stored in i
. This additional attempt to read the value of i
has undefined has undefined behavior.
Compliant Solution
This compliant solution is appropriate when the programmer intends for both arguments to func()
to be equivalent:
...
Code Block | ||||
---|---|---|---|---|
| ||||
extern void c(int i, int j); int glob; int a() { return glob + 10; } int b() { glob = 42; return glob; } void f() { c(a(), b()); } |
The order in which a()
and b()
are called is unspecified; the only guarantee is that both a()
and b()
will be called before c()
is called. If a()
or b()
rely on shared state when calculating their return value, as they do in this example, the resulting arguments passed to c()
may differ between compilers or architectures.
...
In this compliant solution, the order of evaluation for a()
and b()
is fixed, and so no no unspecified behavior occurs:
Code Block | ||||
---|---|---|---|---|
| ||||
extern void c(int i, int j); int glob; int a() { return glob + 10; } int b() { glob = 42; return glob; } void f() { int a_val, b_val; a_val = a(); b_val = b(); c(a_val, b_val); } |
Risk Assessment
Attempting to modify an object in an unsequenced or indeterminately sequenced evaluation may cause that object to take on an unexpected value, which can lead to unexpected program behavior.
...