The undefinedness of a common expression.

W

Wojtek Lerch

OK, now I'm confused -- did you mean that I misinterpreted his square
brackets added to the text quoted from the Standard, or did you mean that I
paraphrased his interpretation accurately but his interpretation was not a
reasonable one?
 
R

Richard Tobin

[/QUOTE]
OK, now I'm confused -- did you mean that I misinterpreted his square
brackets added to the text quoted from the Standard, or did you mean that I
paraphrased his interpretation accurately but his interpretation was not a
reasonable one?

The latter.

-- Richard
 
A

Andrew Poelstra

["Followup-To:" header set to comp.lang.c.]
That's why Eric posted it!

-- Richard

Oh! I missed a level of followup nesting (perhaps I am colorblind
without coffee, or else slrn did not color it) and thought Eric
had posted both the question and the diagram.

Of course, that would be awfully silly of him - indeed, he's plenty
smart enough to see the problem without any diagrams at all.
 
L

lawrence.jones

In comp.std.c frank said:
Did they add a new variety of sequence point?

No, we codified that there are more things that affect sequencing (e.g.,
data flow dependencies) and rewrote the rule accordingly. The new rule
more clearly expresses the intended behavior.
 
L

lawrence.jones

In comp.std.c Kaz Kylheku said:
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.

No. The rule says that the *prior* value may only be read to determine
the value to be stored; that's reading the new value, not the prior one.
 
B

Ben Bacarisse

Kaz Kylheku said:
Kaz Kylheku said:
On 2010-01-15, Ben Bacarisse <[email protected]> wrote:
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.

OK. That being so, I think it best to leave this as it stands. You
understand my point of view and I am pretty sure I have a good grasp
of yours.

<snip>
 
W

Wojtek Lerch

No. The rule says that the *prior* value may only be read to determine
the value to be stored; that's reading the new value, not the prior one.

Is it? I've always believed that an assignment operator returns the value
that it also stores in the object, *without* reading it back from the
object, and that the Standard's description in terms of "the value of the
object after the assignment" was just a clumsy wording (no offense) that
wasn't meant to imply a read access. If that's not the intended
interpretation, then why doesn't the standard say that the new value is
stored before the assignment expression yields its value? Why does it talk
about the next sequence point, if it doesn't mean to allow the store to
happen *after* the value has been returned to any operator that the
assignment may be an operand of?

(What's even more curious is why it talks about the "previous" sequence
point. Does is mean to say that the store may happen before the two
operands of the assignment have been completely evaluated? In rare cases,
such as "x = y & 0", the value of an operand may be known before its
evaluation is finished -- does the standard mean to allow x to be written to
before y is read?)

And closer to the original topic, was the "only to determine the value to be
stored" part intended to simply say that any read accesses to the object
must belong to the right argument of the assignment (rather than to the left
argument or some expression outside of the assignment expression whose
evaluation may be interleaved with the assignment)? I thought it was *not*
meant to forbid things like

x = y = x+1;

where the old value of x is read not *only* to determine the value to be
stored in x, but also to determine the value to be stored in y.
 
W

Wojtek Lerch

Francis Glassborow said:
Actually, of the top of my head, it better not mean that the store is read
to obtain the value just stored because that would mean that assigning to
a volatile variable has an unspecified value.

I don't think *that* would be much more of a problem than the fact that an
explicit read from a volatile is just as unspecified. But in my experience,
most code that assigns to a volatile doesn't use the result of the
assignment operator. What I think would be a much bigger problem is that
there would not be a way to write to a hardware register without reading
back from it. For instance, there's hardware around where a write sends a
command and a read from the same location confirms an interrupt -- it can be
a problem if you read the location without receiving an interrupt first.
 
P

Phil Carmody

Francis Glassborow said:
Actually, of the top of my head, it better not mean that the store is
read to obtain the value just stored because that would mean that
assigning to a volatile variable has an unspecified value.

Good. I certainly want most of my volatile hardware registers
to have unspecified values after I've assigned to them. Otherwise
I'd never bother reading from them after the first assignment,
would I?

Phil
 
T

Tim Rentsch

Francis Glassborow said:
Actually, of the top of my head, it better not mean that the store is
read to obtain the value just stored because that would mean that
assigning to a volatile variable has an unspecified value.

Oh it's worse than that. Whether or not the value is read
back, assigning to a volatile variable is undefined behavior
(unknown side-effects, right?). And so is reading from one.

In practice of course this doesn't matter because the behavior
is actually defined, just by the underlying hardware rather
than the implementation. But it's good to remember that any
use of volatile is inherently not completely portable.
 
W

Wojtek Lerch

Phil Carmody said:
Good. I certainly want most of my volatile hardware registers
to have unspecified values after I've assigned to them. Otherwise
I'd never bother reading from them after the first assignment,
would I?

The values of your hardware registers are unspecified by the C standard
anyway, but hopefully specified by the manufacturer of your hardware. But
this is not about the values of your registers -- it's about the values of
your assignment expressions. Does an assignment simply report the value
that it writes to the object, or does it have to read back from the object
and return whatever it finds there? In other words, when "volatile char
*ptr" points to a register that always returns zero when read, does

int val = *ptr = 1;

initialize "val" to zero or one?

Most code that deals with hardware registers doesn't use the value returned
by an assignment. If the C standard insisted that an assignment must read
from the register after writing to it anyway, that would be merely a waste
of time for most hardware. But in some hardware, reading from a register
actually consumes the data read -- wouldn't it be bad if a write to a serial
port's output register had the side-effect of consuming a byte from its
input queue?
 
L

lawrence.jones

In comp.std.c Wojtek Lerch said:
Is it? I've always believed that an assignment operator returns the value
that it also stores in the object, *without* reading it back from the
object, and that the Standard's description in terms of "the value of the
object after the assignment" was just a clumsy wording (no offense) that
wasn't meant to imply a read access.

That was certainly the intent, although actually doing a read would also
be an acceptable implementation. But a number of people have argued
that the wording in the Standard requires a read. If you think that (as
Kaz seems to), the value read would be the new value, not the prior
value.
(What's even more curious is why it talks about the "previous" sequence
point. Does is mean to say that the store may happen before the two
operands of the assignment have been completely evaluated? In rare cases,
such as "x = y & 0", the value of an operand may be known before its
evaluation is finished -- does the standard mean to allow x to be written to
before y is read?)
No.

And closer to the original topic, was the "only to determine the value to be
stored" part intended to simply say that any read accesses to the object
must belong to the right argument of the assignment (rather than to the left
argument or some expression outside of the assignment expression whose
evaluation may be interleaved with the assignment)?

Yes.
 
F

frank

No, we codified that there are more things that affect sequencing (e.g.,
data flow dependencies) and rewrote the rule accordingly. The new rule
more clearly expresses the intended behavior.

Ok. I'd heard that the committee wasn't even considering major
revisions. It's an issue not just for C but other syntaxes as well, to
wit, will they follow the C definitions or strike out on their own.
 
W

Wojtek Lerch

That was certainly the intent, although actually doing a read would also
be an acceptable implementation.

For non-volatile objects, sure, because the as-if rule allows it. But for
volatile objects, doing a read where the abstract machine isn't doing one
would be wrong, wouldn't it?

Either an assignment is required to return the value it stores, or it's
allowed to return whatever value it finds in the object after writing to it,
even if the object is volatile and the value is different. I don't think
you can have it both ways, can you?
But a number of people have argued
that the wording in the Standard requires a read. If you think that (as
Kaz seems to), the value read would be the new value, not the prior
value.

And the store must happen before the assignment operator reads its value
back from the object, and the words about it happening before the next
sequence point are unnecessary and redundant.

Then the words about the write happening after the previous sequence point
are unnecessary and redundant, aren't they? The write happens after the
operands of the assignment are evaluated, but before the next sequence
point. Or, according to Kaz, just after the operands are evaluated, before
the value is read back and then passed on to any surrounding operators.

Either way, the restriction on reading the old value really applies to all
reading from the object between the surrounding sequence points, doesn't it
(other than the read-back that Kaz believes is part of the assignment) --
since the store may be the last thing that happens before the next sequence
point, there's no way to reliably read the *new* value from the object
before the next sequence point, is there?

I vaguely remember that the formal model of sequence points that ended up
not making into the standard a while ago seemed to allow the left argument
to an assignment to read the value, like the a[a[0]]=1 example does. Was
that one of the reasons why it was dropped? Or was my interpretation of it
incorrect?...
 
K

Kaz Kylheku

No. The rule says that the *prior* value may only be read to determine
the value to be stored; that's reading the new value, not the prior one.

An object has just one value; prior and new refers to different times at
which that value is observed.

If an access unambiguously reads either the prior or new value,
that means it is well-defined.

So, if I understand it right, i = 1 is well-defined, because it accesses
and yields the new value of i, which we know it does unambiguously
because it is well-defined. :)
 
J

James Kuyper

Also, the new value does not have to be read from 'i', and will almost
certainly not be. The standard merely requires that the assignment have
the same value as the object after assignment; a conforming
implementation does not need to retrieve that value from 'i' to meet
that requirement. All that it needs to do is keep the value in the
register after writing it to memory.
An object has just one value; prior and new refers to different times at
which that value is observed.

int i =1;
i = 3;

If you insist on saying that the object 'i' has just one value, which
can be observed to be '1' prior to the assignment statement, and can be
observed to be 3 after the assignment statement, the more conventional
way to describe the same events is by saying that the value of 'i' prior
to the assignment was 1, and that the new value after the assignment is
3. If f you care to communicate clearly with people about the meaning of
the C standard, you should follow those conventions; otherwise
statements such as the yours above will be correctly interpreted as
nonsense.
If an access unambiguously reads either the prior or new value,
that means it is well-defined.

In itself, yes. However, the behavior can become undefined during the
evaluation of a statement that can modify the value, if the access
unambiguously reads the prior value, and uses it for any purpose other
than computing the new value (at least under C99 rules - I gather that
the C1x rules will be a bit more flexible).
So, if I understand it right, i = 1 is well-defined, because it accesses
and yields the new value of i, which we know it does unambiguously
because it is well-defined. :)

"i = 1;" is well-defined because the required semantics does not in any
way involve reading the prior value. There's nothing circular about the
logic.
 
W

Wojtek Lerch

James Kuyper said:
The standard merely requires that the assignment have the same value as
the object after assignment; a conforming implementation does not need to
retrieve that value from 'i' to meet that requirement.

When the object is a regular non-volatile variable, sure; but the
interesting case is an assignment to a volatile object. Imagine that you're
assigning 1 to a hardware register that always returns zero when read? What
is "the value of the object after the assignment" in that case -- is it one
or is it zero?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,994
Messages
2,570,223
Members
46,815
Latest member
treekmostly22

Latest Threads

Top