There are several interesting questions raised here regarding undefined behaviour in C. One of them is (slightly modified)
Does the following piece of code result in undefined behaviour?
int i = 0, *a = &i; // Line 1 a[i] = i + 1; // Line 2
Since there is no concrete answer to this part of the question there, and I am interested in knowing the behaviour in C++, I am raising it again here.
Rule #2 from Undefined Behavior and Sequence Points says
Furthermore, the prior value shall be accessed only to determine the value to be stored
Clearly in the example above, the value is being accessed twice: a[i]
(lhs) and i
(rhs), and only one of them (the rhs) determines the value to be stored.
Does Line 2 violate the rule above and result in undefined behaviour in C++03?
There is some confusion as to whether i
is modified at Line 2?
I would like to point out one thing:
a[i] = i
does not always lead to well defined behaviour. The reason why the behaviour is well defined in the case specified, is because of the initial valuesi
anda
.Let me elaborate:
For any other initial value of
i
we are accessing a different memory location from that ofi
itself, which produces undefined behaviour.No it doesn't. The first line has a sequence point (the comma), so it is not undefined behaviour:
The second line is perfectly normal.
Since
i + 1
creates a temporary value,i
gets modified only once, on the assignment. This however would be undefined behaviour:Undefined behavior in this case would only take place if you modify the same memory address without a sequence point between the modifications. Specifically, the C99 spec, section 6.5/2 states,
In your case no modification of the same memory address takes place between sequence points, therefore there is no undefined behavior.
Let us decompose the expression
a[i] = i + 1
will you ?Effectively,
a[i]
refers to&i
however note that neithera[i]
nori+1
modifiesi
.i
is only modified when=
(the assignment itself) is executed.Since the operands of any function need be evaluated before this function takes effect, this is actually equivalent to:
It is true that
=
is somewhat special in that it is built-in and does not result in a function call, still the evaluation of both operands are sequenced before the actual assignment, so they are first evaluated prior toi
being modified, anda[i]
(which points toi
location) is being assigned to.int i = 0, *a = &i;
there is a sequence point between declarations, therefore no UB here. However take a note that it is a bad idea to declare/define variables that way. Any normal coding standard would tell you declare one variable per line.
a[i] = i;
The
i
is not changed in any way, therefore no UB here either.This will result in undefined behavior in C++03, and well-defined behavior in C++11.
C++03: Undefined Behvaior
From the C++03 standard, section 5 paragraph 4:
Note the second sentence: The previous value of
i
can only be used to determine the value to be stored. But here it is also used to determine the array index. So because this assignment will modifyi
,a[0] = i+1
is well defined, whilea[i] = i+1
is not. Note that the assignment does not generate a sequence point: only the end of the full expression (the semicolon) does.C++11: Well defined behavior:
C++11 got rid of the notion of sequence points, and instead defines which evaluations are sequenced before which.
From the standard, section 1.9 paragraph 15:
Both operands of the assignment operator are sequenced before the actual assignment. So both
a[i]
andi+1
will be evaluated, and only then willi
be modified. The result is well defined.