Eric said:
(Sigh.) All right, now define "time" and "same," grounding
both definitions in terms already defined by the Standard.
I meant "simultaneous" as outside of a C Standard. Posters have offered
that one potential reason why the Standard doesn't define side effect
order within sequence point bounds is because there is or could be
hardware where a simultaneous read and write to the same object could
cause an exception. If that's a relevant reason, then so should this
question about simultaneity be relevant. Perhaps it's out-of-scope for
what you're interested in discussing. If so, I readily accept that.
Perhaps one of the posters who offered that reason might have something
to say about the matter.
A conforming implementation must (among other things) define
what an "access" to a volatile-qualified object is. A conforming
implementation is not obliged to sequence things one way or another
simply because there's a `volatile' lurking somewhere about.
Aha. Ok. Where "one way" might be "simultaneously". So a conforming
implementation has _two_ chances to discard 'volatile'.
volatile int a = 1;
a = a + a;
1. "I define the actual semantics to be one-to-one with the abstract
semantics. 'volatile' is redundant."
2. "I define that all reads of objects within the same sequence point
bounds shall occur no more than once per object. At each sequence
point, I will read all values for all objects read within an expression
no more than once. I will pend all modifications for immediately before
the next sequence point; these will be scheduled to occur simultaneously."
Seem ok?
Assuming not, and further assuming a particular scenario where there is
no unknown factor to modify the 'volatile' array below, is the
output of
the following program well-defined to be one of: { 0, 5, 9 }? Or is the
output unspecified or implementation-specific?
If you're assuming no external modification, I don't see how
`volatile' enters into the question. Accessing a volatile variable
does not introduce a sequence point, if that's what you're getting at.
No, I wasn't getting at that. I'm trying to understand the intentions of
a C Standard in regards to 'volatile'. On the one hand, it suggests that
if an implementation's semantics correspond one-to-one with the abstract
semantics, then 'volatile' would be redundant[1]. On the other hand,
implementations define both what constitutes an access for a 'volatile'
object[2] as well as the order of side effects between sequence
points[3].
You're right about [1] and [2], but completely wrong about [3].
The quoted text says the ordering of side-effects is "unspecified,"
not "implementation-defined." The implementation is not obliged to
define any ordering for side-effects. Corollary: The implementation
is not required to use a consistent ordering, not even from one
evaluation of the same source expression to the next.
Uhh... If the Standard doesn't define the ordering of side effects and
the implementation doesn't, then who does? Even a random side effect
order is a definition.
I think what you're getting at is that it doesn't need to be documented
by the implementation. If so, then I agree.
Unfortunately, the constraint of using terms exactly as they appear in
the Standard makes it confusing if I type "implementation-defined".
What I should have typed was "implementation-chosen". Sorry about that!
#include <stdio.h>
int main(void) {
volatile int arr[2];
arr[0] = 1;
arr[1] = 5;
arr[0] = arr[arr[0]] + --(arr[arr[0] - 1]) + arr[arr[0]];
Looks like undefined behavior to me, for the same reason
discussed (at wearying length) in the "C Test Incorrectly Uses
printf() - Please Confirm" thread.
It's clear from the reference you pointed out in that thread[5] that if
the big expression above modifies some object and tries to do so twice
within the same sequence point bounds, that it's outside of the C
Standard.
True, but that's not what the referenced thread is about. The
objectionable expression attempts to modify an object and to use it
for purposes other than determining the new value, and that's that.
(Since the behavior is undefined, it's not possible to tell for sure
whether the expression attempts to modify one object twice.)
Right, in regards to the other thread. But in the big expression above,
'arr[0]' is being used to determine the new value. The '--'
modification side effect might or might not be on the same object,
depending on the circumstances, and might not be known one way or the
other until run-time.
So I'll ask if we can really call it undefined behaviour by looking at
it. I think in this case that it's implementation-chosen... A
combination of factors including implementation-defined and unspecified,
as you've mentioned. As in, 6.5p2 cannot apply here (above) until after
those bits are known, right?
The name you're searching for is "nonexistent," or maybe even
"impossible." (The exhibition of a counter-example would be a boon
to the practice of programming, should you feel so inclined.)
Ha! Nice one.
I was thinking of a particular implementation acronym
that's been passed around a bit and that's a bit too dreadful for me to
repeat. But yes, such an implementation could make short work of
assumptions that fall outside of a C Standard... If certain tricky
details could be clarified.
There's a footnote that says as much -- and what's more, you've
read the footnote.
Well, the non-normative footnote is for "information only", whereas
'register' and 'restrict' are normative, so it's worth asking opinions on.
Additionally, 'register' has some Standard-defined consequences. Is
that so for 'volatile'? I think you're stating that 'volatile' does not
have Standard-defined consequences.
Thank you, as always.