S
sfuerst
Hello, back in 2002 there was a long discussion in these newsgroups
about the undefinedness of the expression:
a[a[0]] = 1; when a[0] begins with the value 0.
The general opinion was that the above invokes undefined behaviour due
to the fact that there is no sequence point in the expression, and
that the value of a[0] is used in a "value computation" unsequenced
with respect to the side-effect of the assignment operator. This is
slightly surprising, with a naive viewpoint that the above "should" be
the same as t = a[0], a[t] = 1; However, code like the above
expression is rare (I only found a single instance in the Linux kernel
source) - so this obscure case can probably be ignored to maintain the
simplicity of the sequence point rules in the standard.
However, there is another, much more common case similar to the above
which appears in real-world code:
node->next->next = something; when node->next begins with the value
'node'. (A circularly linked list one link long.)
Using the offsetof() macro, and the a <---> *(a + b) identity, this
new expression may be transformed into the first undefined one. This
is a problem. Should such common practice be undefined? If not, then
there may be a defect in the standard.
One possible solution is to make pointer dereferencing (or accessing
an array) contain a sequence point between the calculation of the
pointer value and its dereference. Most users of C probably have the
mistaken impression that such a sequence point already exists. (The
abstract machine "obviously" needs to evaluate the value of an address
before that address may be dereferenced.) However, an argument can be
made that the current undefined behaviour allows compiler
optimizations that otherwise wouldn't be possible due to the knowledge
that the undefined situation cannot occur.
Steven
about the undefinedness of the expression:
a[a[0]] = 1; when a[0] begins with the value 0.
The general opinion was that the above invokes undefined behaviour due
to the fact that there is no sequence point in the expression, and
that the value of a[0] is used in a "value computation" unsequenced
with respect to the side-effect of the assignment operator. This is
slightly surprising, with a naive viewpoint that the above "should" be
the same as t = a[0], a[t] = 1; However, code like the above
expression is rare (I only found a single instance in the Linux kernel
source) - so this obscure case can probably be ignored to maintain the
simplicity of the sequence point rules in the standard.
However, there is another, much more common case similar to the above
which appears in real-world code:
node->next->next = something; when node->next begins with the value
'node'. (A circularly linked list one link long.)
Using the offsetof() macro, and the a <---> *(a + b) identity, this
new expression may be transformed into the first undefined one. This
is a problem. Should such common practice be undefined? If not, then
there may be a defect in the standard.
One possible solution is to make pointer dereferencing (or accessing
an array) contain a sequence point between the calculation of the
pointer value and its dereference. Most users of C probably have the
mistaken impression that such a sequence point already exists. (The
abstract machine "obviously" needs to evaluate the value of an address
before that address may be dereferenced.) However, an argument can be
made that the current undefined behaviour allows compiler
optimizations that otherwise wouldn't be possible due to the knowledge
that the undefined situation cannot occur.
Steven