Kaz Kylheku said:
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.
<snip discussion of sub-expression sequencing>
The general opinion was that the above invokes undefined behaviour due
General or not, that is not a particularly well-informed opinion.
<snip more about sequencing>
I don't disagree with your arguments about sequencing, logic, and
causality, but I don't see how you can dismiss the conclusion above so
lightly -- particularly without any reference to the text that, in my
view, renders it undefined.
The oft-quoted 6.5 paragraph 2 reads:
"Between the previous and next sequence point an object shall have
its stored value modified at most once by the evaluation of an
expression. Furthermore, the prior value shall be read only to
determine the value to be stored." [footnote numbers removed]
This text can be parsed as:
[ Furthermore, the prior value shall be read only ] to
determine the value to be stored."
Are you being serious? It seems unlikely. In case you are, I have
these arguments:
Yep.
And note that the parse that many people are assuming rules out
the assignment operator completely. Code such as
i = 1;
is undefined. Here i is modified, but it is also read, not for
computing the value to be stored. The value of an assignment expression
is that of the lvalue, after the assignment, you see. So the lvalue
is read by this expression to fetch this value. That ``after
the assignment'' bit appears like it imposes an order, but it's
not a sequence point. So the expression statement i = 1; contravenes the
naive parsing of paragraph 2.
limits, but not, I think when followed by "to". The OED uses "only
to" as an example of only preceding the thing it limits (1899 Literary
Guide 1 Oct. 146/2 "Certain doctrines were imparted only to
initiates").
Here ``to initiates'' is a very different kind of clause from ``to
determine ...'', because the ``determine ...'' part is a full sentence
in its own right. Also, ``read'' and ``impart'' are semantically
different. The relationship between ``doctrine'' and ``impart''
is limited. What else can you do with a doctrine and an initiate,
besides impart? Why ``only impart''? Doctrines were only imparted on the
initiates (but not also tatooed on their foreheads?). Nah; such
tattooing is subsumed under extended semantics of imparting, right?
Read is different. In computing, we even have the phrase ``read-only'';
there is a relationship between read and only, which means that
writing is excluded.
Your interpretation is more naturally written "the prior
value shall only be read to determine the value to be stored".
True. All kinds of things are more naturally wirtten than some of the
long-winded gobbledygook in the ISO C standard.
Your parse (if I have it right) is that to determine the value to be
stored, only reading of the prior value is permitted.
Permitted, but of course not required.
What actions on
the prior value is your interpretation intended to prohibit? Would it
not prevent the value from being doubled to determine the value to
be stored (i = i*2
?
Doubling does not destroy the value; it produces a new value which is
twice the previous one, in the absence of overflow.
Clearly the ``value'' here refers to manipulation of the object: the
stored value. The term value has multiple meanings; there is the stored
value in an object which can be read, or the value of an expression.
The value of the expression i*2 is no longer the stored value in the
object i. All that i*2 does to the stored value is read it.
In your reading of it, does the sentence have any purpose?
I suspect that it doesn't, and that it's not alone in not having one.
I.e. what
kinds of expression would be defined were it not for that extra
sentence?
None, but clearly, if a value modified by some store is written before
that store, that is not a good thing. This may not be; it may be read
only.
Your phrase "the store" is a slight of hand.
Not intended.
Which is "the store"
before which the prior value can not be written in:
x = i++;
the prior value of x cannot be written prior to the assignment x =
and the prior avlue of i cannot be written prior to the incremnt i++.
Each modified object has a prior value. Each modified object is modified
only once, hence it cannot be modified prior to that one and only
modification.
and why would the standard wish to say which store comes first? The
It doesn't. The order in which the side effects to x and i happen
is not specified.
prior value of i may very well be written (to x) before the store to
i. If you intended to limit this remark to expressions with only one
object being modified, the you are saying that "the prior value can't
Paragraph 2 is not limited to expressions with just one object modified,
but it's clear that for some object that is modified, the prior value
and store refer to the same object.
be written before it is written".
Yes, precisely. Isn't that clear? If a value is written before it is
written, then it's modified twice. So this, uh, reinforces the first
sentence of the same paragraph. That's it!
See, people are just reading it wrong. There is no document defect to see
here, people; move along.
If you are right, there is a defect because the second example in
footnote 73 is then wrong. a[i++] = i; is fine by your reading, is it
not?
No, it's not fine.
This expression is ruled out by the unspecified order of evaluation of
subexpressions (except for the noted operators) and by
the unspecified order of side effect completion.
The major connective of this expression is the = operator, whose
constituents are a[i++] and i, which, being subexpressions of an
unsequenced operator, may be evaluated in either order. Moreover, the
completion of the side effect emanating from the one subexpression is
not required as a dependency for the computation of the other. Clearly,
this is ambiguous. The i++ effect may complete before the i is accessed,
after, or could be in progress while i is accessed. You will have
an actual portability problem with actual compilers if you write
this expression.
Now we could add some superfluous text to the standard to try to capture
this idea, but it's not necessary; the undefinedness follows straight
from paragraph 3.
The defect is that the example in the footnote is irrelevant to
the paragraph to which the footnote is attached. That paragraph
does not render it undefined; however, the next paragraph does.
The footnote could be moved to the next paragraph and reworded
to say that it pertains to ``this and the preceding
paragraph''.