Andy Lomax <ab***@[127.0.0.1]> writes:
On Mon, 20 Jun 2005 16:13:01 GMT, la************@ugs.com wrote:
Andy Lomax <ab***@[127.0.0.1]> wrote [quoting the C standard]:
If an attempt is made to modify the result of an assignment
operator or to access it after the next sequence point, the
behavior is undefined.
What does this actually mean? Can anyone give me a code example that
leads to undefined behaviour?
struct { int a[2]; } s, t;
int *p;
(s = t).a[0] = 3; // attempting to modify the result of an assignment op.
p = (s = t).a;
p[0]; // attempting to access the result after the next s.p.
Very interesting - gcc/C90 gives a syntax error ('invalid use of
non-lvalue array for 'p=(s=t).a'), but gcc/C99 compiles Ok, but I
don't understand why.
The spec says:
An assignment expression has the value of the left operand after the
assignment, but is not an lvalue.
So how is it possible to write '(s=t).a[0] = 3'?
The result of the assignment expression is not an lvalue, but ...
The expression (s=t) yields a value (not an lvalue) of the above
struct type.
(s=t).a is of type int[2], which is implicitly converted to int*.
(This issue wouldn't occur if it were of type const int*, but the
language doesn't say there's a const, so there isn't.
(s=t).a[0] is therefore an lvalue of type int. There's no problem if
you want to read this value, but attempting to modify it invokes
undefined behavior.
Secondly, surely there's no problem accessing the result of an
assignment op *after* the next sequence point. Wouldn't the problem
arise if it was accessed *before* the next sequence point, which is
potentially before the update side-effect has taken place?
A struct assignment copies a struct value to a struct object and
yields the assigned value. Imagine that this value is stored in some
temporary location that no longer exists after the assignment (or
after the next sequence point). The assignment
p = (s = t).a;
grabs and saves the address of something within that temporary
storage. After the next sequence point, the storage should be assumed
to be gone, so any attempt to examine it invokes undefined behavior.
If you attempt to do something similar before the next sequence point,
either it's ok (because the temporary is still there), or it invokes
undefined behavior because of the other existing rules.
Note that something like this:
x = y;
x;
does not access the result of the assignment; it access the value of
x, which was set by an assignment that was completed before the
previous sequence point. The "result of the assignment" is a
temporary value that in most cases cannot be accessed as an object.
The obscure case above involving assignments of structures containing
arrays is, as far as I know, the only kind of thing that can cause
this problem.
--
Keith Thompson (The_Other_Keith)
ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.