Does Standard C make any guarantee to the order in which expressions inside multidimensional array indices are evaluated? Is there a defined sequence point between each successive []
while indexing a multidimensional array?
For example if I have this:
int a(void) {
puts("a");
return 0;
}
int b(void) {
puts("b");
return 1;
}
int c(void) {
puts("c");
return 2;
}
int d(void) {
puts("d");
return 3;
}
Will the following have predictable behavior?
int arr[4][4][4][4];
arr[a()][b()][c()][d()] = 1;
Are the functions guaranteed to be called in any particular order? On GCC they were called left to right resulting in this:
a
b
c
d
Another example is this:
int i = 0, arr[4][4][4][4];
arr[i++][i++][i++][i++] = 1;
Will that always be equivalent to arr[0][1][2][3] = 1;
or will that cause undefined behavior due to accessing and modifying i
without a defined sequence point between them?
Note: Neither of these examples have to do with precedence which is the placement of implicit parenthesis or the order in which the operators operate on their operands. The question is about sequencing which is the order in which the operands themselves are evaluated and their side effects are performed.
Will the following have predictable behavior?
int arr[4][4][4][4]; arr[a()][b()][c()][d()] = 1;
No.
While the evaluation of the array elements will be evaluated from left to right, as one is an operand to the next, there is no guarantee that the array indexes themselves will be evaluated from left to right.
To be more specific, arr[a()]
is evaluated before arr[a()][b()]
, which is evaluated before arr[a()][b()][c()]
, which is evaluated before arr[a()][b()][c()][d()]
. However, a()
, b()
, c()
, and d()
may be evaluated in any order.
Section 6.5p3 of the C standard regarding expressions states:
The grouping of operators and operands is indicated by the syntax. Except as specified later, side effects and value computations of subexpressions are unsequenced
Sections 6.5.2.1 regarding array subscripting makes no mention of sequencing of the operands E1[E2]
, although it does state that the prior expression is exactly equivalent to (*((E1)+(E2)))
. Then, looking at section 6.5.3.2 regarding the indirection operator *
and section 6.5.6 regarding the additive operator +
, neither make any mention of the evaluation of their operands being sequenced in any way. So 6.5p3 applies, and the functions a
, b
, c
, and d
may be called in any order.
For the same reasons, this:
arr[i++][i++][i++][i++] = 1;
Triggers undefined behavior since the evaluation of the array indices are unsequenced with relation to each other, and you have multiple side effects on the same object without a sequence point.