473,505 Members | 14,950 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Multiple Assignment Evaluation Debate

Hi All,

A coworker and I have been debating the 'correct' expectation of
evaluation for the phrase a = b = c. Two different versions of GCC
ended up compiling this as b = c; a = b and the other ended up
compiling it as a = c; b = c. (Both with no optimizations enabled).
How did we notice you may ask? Well, in our case 'b' was a memory
mapped register that only has a select number of writable bits. He
claims it has been a 'C Standard' that it will be evaluted as a = c; b
= c. I personally believe that it would make more sense for it to be
evaluated as b = c; a = b, although I would never write code that has a
questionable operation. Can anyone settle this debate?

Mar 10 '06
77 4649

Vladimir S. Oka wrote:
On Friday 17 March 2006 15:27, en******@yahoo.com opined (in
<11**********************@j52g2000cwj.googlegroups .com>):

Vladimir S. Oka wrote:
On Friday 17 March 2006 04:48, en******@yahoo.com opined (in
<11*********************@i39g2000cwa.googlegroups. com>):

>
> pete wrote:
>> en******@yahoo.com wrote:
>> >
>> > Micah Cowan wrote:
>> > > Michael Mair <Mi**********@invalid.invalid> writes:
>> > >
>> > > > Richard G. Riley schrieb:
>> > > > > On 2006-03-12, pete <pf*****@mindspring.com> wrote:
>> > > > >
>> > > > >> I'm coming around to thinking that 6.5 [#2] is relevant,
>> > > > >> and that p = p->next = q
>> > > > >>is undefined, and not just unspecified.
>> > > > > but
>> > > > > p=(p->next=q);
>> > > > > is fine? I hope .
>> > > >
>> > > > No. Whether you write
>> > > > a = b = c;
>> > > > or
>> > > > a = (b = c);
>> > > > does not change anything -- apart from clarifying your
>> > > > intent. You still are modifying p twice between sequence
>> > > > points
>> > >
>> > > Well, no he's not.
>> > > But he's reading its prior value for purposes other
>> > > than to determine the value stored, so same deal.
>> >
>> > Look again. Reading p is necessary to evaluate p->q = next,
>>
>> No, it isn't.
>> The value of (p->q = next) is (next)
>
> The value of p->q = next is next. But in order to get the
> value, the assignment p->q = next must _have been
> evaluated_, which needed both operands. Evaluation includes
> all the actions in the Semantics paragraph, which includes
> starting the side effect of storing the value.

I think pete is right. The compiler _knows_ that the result of (p->q
= next) _will_be_ next before it even produces any code, and can use
that knowledge once it does get to producing some.


You've fallen into the trap of arguing based on what a
compiler might be capable of. Regardless of what the
compiler knows, it's still obliged to produce code that
behaves according to how the Semantics paragraphs and
everything else in the standard says it must.


But it still does not evaluate p->q in order to assign next to it. What
is evaluated is next, and its value is /assigned/ to p->q. Next, the
assignment is evaluated and assigned to p. The assignment evaluates to
next, but I don't think that compiler is obliged to do that in any
particular way.


Sorry, the compiler _is_ obliged to do the evaluation as per the
Semantics description. The Semantics paragraphs in 6.5.16
specify _both_ that the store happens and what the value is.
(Yes, the side effect of the store may happen later.) Where in
the standard is there any statement that says an expression
(_any_ expression) may yield a value _before_ it has been
evaluated?

Mar 18 '06 #51

Chris Torek wrote:
[on whether
p = p->next = next;
could have undefined behavior]
Vladimir S. Oka wrote:
I think pete is right. The compiler _knows_ that the result of (p->q =
next) _will_be_ next before it even produces any code, and can use that
knowledge once it does get to producing some.

In article <11**********************@j52g2000cwj.googlegroups .com>
<en******@yahoo.com> wrote:
You've fallen into the trap of arguing based on what a
compiler might be capable of. Regardless of what the
compiler knows, it's still obliged to produce code that
behaves according to how the Semantics paragraphs and
everything else in the standard says it must.


This is correct -- in order to claim to compile Standard C, a C
compiler must obey the standard -- but the question is whether
"everything else in the standard" actually *says* that

p = p->next = next;

has to have defined behavior. You and I may think it is bizarre
and wrong if the actual wording in the Standard fails to require
this to work the "obvious" and "correct" way. Unfortunately, those
who argue that both C89 and C99 fail to require this to work, do
in fact seem to have a leg to stand on, as the saying goes.


If you mean there are more than a few people that believe that
p = p->next = next are undefined, I agree with you.

The problem is, none of their arguments are convincing. They all
boil down to the premise that an expression can yield a value
before it has been evaluated. But no one has cited any statement
from the standard that says this is allowed. Usually the arguments
are of the form "I can imagine a compiler doing this, so it must
be allowed." That's a bogus argument.

Let me put it as a question - are you aware of any statement
in the standard that says an expression may yield a value
before it's been evaluated?
(The standard has a number of defects, and I consider this to be
one of them, albeit a minor one. Someone's -- I have forgotten
whose -- proposed annex to the C99 standard, with a formal
model for deciding sequence points, would have at least provided
a definitive answer. But that annex did not make it in.)


I wonder how many people took the trouble to read _any_ of the
formal models--there are at least three or four generally
available--before considering their positions or framing their
arguments.

Mar 18 '06 #52

Micah Cowan wrote:
en******@yahoo.com writes:
pete wrote:
No, it isn't.
The value of (p->q = next) is (next)


The value of p->q = next is next. But in order to get the
value, the assignment p->q = next must _have been
evaluated_,


Wrong. The assignment itself need not have taken place. If you really
/did/ understand sequence points, you would know this.

As far as C is concerned, an implementation is more than welcome to do

p = next;
p->q = next;

That's why sequence points are very important.


Ahh, the old "you don't know what you're talking about" defense.
A bold ploy. Of course your statement presupposes that _you_ do
know what you're talking about. The problem is, you haven't
given any supporting statements for either opinion. Or, for that
matter, your opinion about how p = p->next = q is evaluated.

Any other unsupported opinions you'd like to express?

Mar 18 '06 #53
en******@yahoo.com opined:

Vladimir S. Oka wrote:
On Friday 17 March 2006 15:27, en******@yahoo.com opined (in
<11**********************@j52g2000cwj.googlegroups .com>):
>
> Vladimir S. Oka wrote:
>> On Friday 17 March 2006 04:48, en******@yahoo.com opined
>> (in
>> <11*********************@i39g2000cwa.googlegroups. com>):
>>
>> >
>> > pete wrote:
>> >> en******@yahoo.com wrote:
>> >> >
>> >> > Micah Cowan wrote:
>> >> > > Michael Mair <Mi**********@invalid.invalid> writes:
>> >> > >
>> >> > > > Richard G. Riley schrieb:
>> >> > > > > On 2006-03-12, pete <pf*****@mindspring.com>
>> >> > > > > wrote:
>> >> > > > >
>> >> > > > >> I'm coming around to thinking that 6.5 [#2] is
>> >> > > > >> relevant, and that p = p->next = q
>> >> > > > >>is undefined, and not just unspecified.
>> >> > > > > but
>> >> > > > > p=(p->next=q);
>> >> > > > > is fine? I hope .
>> >> > > >
>> >> > > > No. Whether you write
>> >> > > > a = b = c;
>> >> > > > or
>> >> > > > a = (b = c);
>> >> > > > does not change anything -- apart from clarifying
>> >> > > > your intent. You still are modifying p twice
>> >> > > > between sequence points
>> >> > >
>> >> > > Well, no he's not.
>> >> > > But he's reading its prior value for purposes other
>> >> > > than to determine the value stored, so same deal.
>> >> >
>> >> > Look again. Reading p is necessary to evaluate p->q
>> >> > = next,
>> >>
>> >> No, it isn't.
>> >> The value of (p->q = next) is (next)
>> >
>> > The value of p->q = next is next. But in order to get
>> > the value, the assignment p->q = next must _have been
>> > evaluated_, which needed both operands. Evaluation
>> > includes all the actions in the Semantics paragraph,
>> > which includes starting the side effect of storing the
>> > value.
>>
>> I think pete is right. The compiler _knows_ that the
>> result of (p->q = next) _will_be_ next before it even
>> produces any code, and can use that knowledge once it does
>> get to producing some.
>
> You've fallen into the trap of arguing based on what a
> compiler might be capable of. Regardless of what the
> compiler knows, it's still obliged to produce code that
> behaves according to how the Semantics paragraphs and
> everything else in the standard says it must.


But it still does not evaluate p->q in order to assign next
to it. What is evaluated is next, and its value is /assigned/
to p->q. Next, the assignment is evaluated and assigned to p.
The assignment evaluates to next, but I don't think that
compiler is obliged to do that in any particular way.


Sorry, the compiler _is_ obliged to do the evaluation as per
the Semantics description. The Semantics paragraphs in 6.5.16
specify _both_ that the store happens and what the value is.
(Yes, the side effect of the store may happen later.) Where
in the standard is there any statement that says an expression
(_any_ expression) may yield a value _before_ it has been
evaluated?


Ok, now my head starts to spin a bit, but bear with me...

Is it right that the original problem statement was:

p = p->next = q;

Assuming it was: `p` is not modified twice, it is read once to
get `next`, and modified once to assign value to it in the
leftmost assignment. Assigning value to `next` does not modify
`p`, right?

Now, I re-read what 6.5.16 has to say, and yes, I know examples
are not normative, but to me Example 2 (6.5.16.1p5) seems to
support the following interpretation of the above statement:

1) `q` is evaluated
2) its value is assigned to `p->next`
3) that value becomes the value of the rightmost assignment
4) that value is assigned to `p`

I read that it happens in the order I give above. Also, `p` is
modified only once (4), and read only once (2).

I think this, now, expresses how I see what happens, and my
reading of the Standard. If it isn't what I said before, it's
completely my fault (assign 20% to English being my second
language).

--
BR, Vladimir

I have seen these EGG EXTENDERS in my Supermarket ...

Mar 18 '06 #54

Vladimir S. Oka wrote:
en******@yahoo.com opined:

Vladimir S. Oka wrote:
On Friday 17 March 2006 15:27, en******@yahoo.com opined (in
<11**********************@j52g2000cwj.googlegroups .com>):

>
> Vladimir S. Oka wrote:
>> On Friday 17 March 2006 04:48, en******@yahoo.com opined
>> (in
>> <11*********************@i39g2000cwa.googlegroups. com>):
>>
>> >
>> > pete wrote:
>> >> en******@yahoo.com wrote:
>> >> >
>> >> > Micah Cowan wrote:
>> >> > > Michael Mair <Mi**********@invalid.invalid> writes:
>> >> > >
>> >> > > > Richard G. Riley schrieb:
>> >> > > > > On 2006-03-12, pete <pf*****@mindspring.com>
>> >> > > > > wrote:
>> >> > > > >
>> >> > > > >> I'm coming around to thinking that 6.5 [#2] is
>> >> > > > >> relevant, and that p = p->next = q
>> >> > > > >>is undefined, and not just unspecified.
>> >> > > > > but
>> >> > > > > p=(p->next=q);
>> >> > > > > is fine? I hope .
>> >> > > >
>> >> > > > No. Whether you write
>> >> > > > a = b = c;
>> >> > > > or
>> >> > > > a = (b = c);
>> >> > > > does not change anything -- apart from clarifying
>> >> > > > your intent. You still are modifying p twice
>> >> > > > between sequence points
>> >> > >
>> >> > > Well, no he's not.
>> >> > > But he's reading its prior value for purposes other
>> >> > > than to determine the value stored, so same deal.
>> >> >
>> >> > Look again. Reading p is necessary to evaluate p->q
>> >> > = next,
>> >>
>> >> No, it isn't.
>> >> The value of (p->q = next) is (next)
>> >
>> > The value of p->q = next is next. But in order to get
>> > the value, the assignment p->q = next must _have been
>> > evaluated_, which needed both operands. Evaluation
>> > includes all the actions in the Semantics paragraph,
>> > which includes starting the side effect of storing the
>> > value.
>>
>> I think pete is right. The compiler _knows_ that the
>> result of (p->q = next) _will_be_ next before it even
>> produces any code, and can use that knowledge once it does
>> get to producing some.
>
> You've fallen into the trap of arguing based on what a
> compiler might be capable of. Regardless of what the
> compiler knows, it's still obliged to produce code that
> behaves according to how the Semantics paragraphs and
> everything else in the standard says it must.

But it still does not evaluate p->q in order to assign next
to it. What is evaluated is next, and its value is /assigned/
to p->q. Next, the assignment is evaluated and assigned to p.
The assignment evaluates to next, but I don't think that
compiler is obliged to do that in any particular way.
Sorry, the compiler _is_ obliged to do the evaluation as per
the Semantics description. The Semantics paragraphs in 6.5.16
specify _both_ that the store happens and what the value is.
(Yes, the side effect of the store may happen later.) Where
in the standard is there any statement that says an expression
(_any_ expression) may yield a value _before_ it has been
evaluated?


Ok, now my head starts to spin a bit, but bear with me...

Is it right that the original problem statement was:

p = p->next = q;


Yes.
Assuming it was: `p` is not modified twice, it is read once to
get `next`, and modified once to assign value to it in the
leftmost assignment. Assigning value to `next` does not modify
`p`, right?

Now, I re-read what 6.5.16 has to say, and yes, I know examples
are not normative, but to me Example 2 (6.5.16.1p5) seems to
support the following interpretation of the above statement:

1) `q` is evaluated
2) its value is assigned to `p->next`
3) that value becomes the value of the rightmost assignment
4) that value is assigned to `p`

I read that it happens in the order I give above. Also, `p` is
modified only once (4), and read only once (2).
Yes. Also the side effect of updating the value of p->next
can happen any time after (2), and the side effect of updating
the value of p can happen any time after (4).
I think this, now, expresses how I see what happens, and my
reading of the Standard. If it isn't what I said before, it's
completely my fault (assign 20% to English being my second
language).


Mar 18 '06 #55
en******@yahoo.com opined:

Vladimir S. Oka wrote:
en******@yahoo.com opined:
>
> Vladimir S. Oka wrote:
>> On Friday 17 March 2006 15:27, en******@yahoo.com opined (in
>> <11**********************@j52g2000cwj.googlegroups .com>):
>>
>> >
>> > Vladimir S. Oka wrote:
>> >> On Friday 17 March 2006 04:48, en******@yahoo.com opined
>> >> (in
>> >> <11*********************@i39g2000cwa.googlegroups. com>):
>> >>
>> >> >
>> >> > pete wrote:
>> >> >> en******@yahoo.com wrote:
>> >> >> >
>> >> >> > Micah Cowan wrote:
>> >> >> > > Michael Mair <Mi**********@invalid.invalid> writes:
>> >> >> > >
>> >> >> > > > Richard G. Riley schrieb:
>> >> >> > > > > On 2006-03-12, pete <pf*****@mindspring.com>
>> >> >> > > > > wrote:
>> >> >> > > > >
>> >> >> > > > >> I'm coming around to thinking that 6.5 [#2] is
>> >> >> > > > >> relevant, and that p = p->next = q
>> >> >> > > > >>is undefined, and not just unspecified.
>> >> >> > > > > but
>> >> >> > > > > p=(p->next=q);
>> >> >> > > > > is fine? I hope .
>> >> >> > > >
>> >> >> > > > No. Whether you write
>> >> >> > > > a = b = c;
>> >> >> > > > or
>> >> >> > > > a = (b = c);
>> >> >> > > > does not change anything -- apart from clarifying
>> >> >> > > > your intent. You still are modifying p twice
>> >> >> > > > between sequence points
>> >> >> > >
>> >> >> > > Well, no he's not.
>> >> >> > > But he's reading its prior value for purposes other
>> >> >> > > than to determine the value stored, so same deal.
>> >> >> >
>> >> >> > Look again. Reading p is necessary to evaluate p->q
>> >> >> > = next,
>> >> >>
>> >> >> No, it isn't.
>> >> >> The value of (p->q = next) is (next)
>> >> >
>> >> > The value of p->q = next is next. But in order to get
>> >> > the value, the assignment p->q = next must _have been
>> >> > evaluated_, which needed both operands. Evaluation
>> >> > includes all the actions in the Semantics paragraph,
>> >> > which includes starting the side effect of storing the
>> >> > value.
>> >>
>> >> I think pete is right. The compiler _knows_ that the
>> >> result of (p->q = next) _will_be_ next before it even
>> >> produces any code, and can use that knowledge once it does
>> >> get to producing some.
>> >
>> > You've fallen into the trap of arguing based on what a
>> > compiler might be capable of. Regardless of what the
>> > compiler knows, it's still obliged to produce code that
>> > behaves according to how the Semantics paragraphs and
>> > everything else in the standard says it must.
>>
>> But it still does not evaluate p->q in order to assign next
>> to it. What is evaluated is next, and its value is /assigned/
>> to p->q. Next, the assignment is evaluated and assigned to p.
>> The assignment evaluates to next, but I don't think that
>> compiler is obliged to do that in any particular way.
>
> Sorry, the compiler _is_ obliged to do the evaluation as per
> the Semantics description. The Semantics paragraphs in 6.5.16
> specify _both_ that the store happens and what the value is.
> (Yes, the side effect of the store may happen later.) Where
> in the standard is there any statement that says an expression
> (_any_ expression) may yield a value _before_ it has been
> evaluated?


Ok, now my head starts to spin a bit, but bear with me...

Is it right that the original problem statement was:

p = p->next = q;


Yes.
Assuming it was: `p` is not modified twice, it is read once to
get `next`, and modified once to assign value to it in the
leftmost assignment. Assigning value to `next` does not modify
`p`, right?

Now, I re-read what 6.5.16 has to say, and yes, I know examples
are not normative, but to me Example 2 (6.5.16.1p5) seems to
support the following interpretation of the above statement:

1) `q` is evaluated
2) its value is assigned to `p->next`
3) that value becomes the value of the rightmost assignment
4) that value is assigned to `p`

I read that it happens in the order I give above. Also, `p` is
modified only once (4), and read only once (2).


Yes. Also the side effect of updating the value of p->next
can happen any time after (2), and the side effect of updating
the value of p can happen any time after (4).


I agree.

However, what is the side effect of updating `p->next`? It's just plain
storing a value into a variable. Again, `p` is not modified, AFAICT.
It's the struct member `next` that is, and `p` is just read to get its
address (`next`'s address).

Whether there's any side effect of updating `p` after (4) is, IMO,
irrelevant to the discussion (again, I can't see any side effect of
storing a value into variable).

I still think the operation in this case has to be equivalent to:

p->next = q;
p = p->next;

--
BR, Vladimir

A lad, at his first copulation,
Cried, "What a sensation! Inflation,
Gyration, elation
Throughout the duration,
I guess I'll give up masturbation."

Mar 18 '06 #56
Vladimir S. Oka <no****@btopenworld.com> wrote:

Now, I re-read what 6.5.16 has to say, and yes, I know examples
are not normative, but to me Example 2 (6.5.16.1p5) seems to
support the following interpretation of the above statement:

1) `q` is evaluated
2) its value is assigned to `p->next`
3) that value becomes the value of the rightmost assignment
4) that value is assigned to `p`


It's a bit more complicated than that. First, the top-level assignment
expression (p = p->next = q) is evaluated. That requires evaluating the
left side (p) to determine the location to store into and evaluating the
right side (p->next = q) to determine the value to store. Those
evaluations can occur in either order. Evaluating the left side is
trivial, but the right side is again an assignment expression, so it is
necessary to evaluate the left side (p->next) to determine a location to
store into and the right side (q) to determine the value to be stored,
again in any order. This time the right side is trivial, but evaluating
the left side requires evaluating p. So, there are *lots* of
evaluations, which are only loosely ordered.

-Larry Jones

Something COULD happen today. And if anything DOES,
by golly, I'm going to be ready for it! -- Calvin
Mar 19 '06 #57
la************@ugs.com opined:
Vladimir S. Oka <no****@btopenworld.com> wrote:

Now, I re-read what 6.5.16 has to say, and yes, I know examples
are not normative, but to me Example 2 (6.5.16.1p5) seems to
support the following interpretation of the above statement:

1) `q` is evaluated
2) its value is assigned to `p->next`
3) that value becomes the value of the rightmost assignment
4) that value is assigned to `p`
It's a bit more complicated than that. First, the top-level
assignment expression (p = p->next = q) is evaluated. That requires
evaluating the left side (p) to determine the location to store into
and evaluating the right side (p->next = q) to determine the value to
store. Those evaluations can occur in either order.


I admit that the normative text of the standard does allow (but not
mandate) such behaviour. However, as I have pointed earlier, the
Example 2 (non-normative, as examples are) suggests that the order of
evaluation is right-to-left.
Evaluating the left side is trivial, but the right side is again an
assignment expression, so it is necessary to evaluate the left side
(p->next) to determine a location to store into and the right side
(q) to determine the value to be stored, again in any order. This
time the right side is trivial, but evaluating the left side requires
evaluating p. So, there are *lots* of evaluations, which are only
loosely ordered.


I know that modifying a value multiple times between sequence points
results in UB, I don't think evaluating something multiple times
(without modifying it multiple times) is a problem.

--
BR, Vladimir

Technological progress has merely provided us
with more efficient means for going backwards.
-- Aldous Huxley

Mar 19 '06 #58
Vladimir S. Oka <no****@btopenworld.com> wrote:

la************@ugs.com opined:

It's a bit more complicated than that. First, the top-level
assignment expression (p = p->next = q) is evaluated. That requires
evaluating the left side (p) to determine the location to store into
and evaluating the right side (p->next = q) to determine the value to
store. Those evaluations can occur in either order.
I admit that the normative text of the standard does allow (but not
mandate) such behaviour. However, as I have pointed earlier, the
Example 2 (non-normative, as examples are) suggests that the order of
evaluation is right-to-left.


No, it most certainly does not. Example 2 is primarily concerned with
the result type of assignment expressions, not order of evaluation.
About the only thing that it implies about order of evaluation is that
an operator's operands must be evaluated before the final result of the
operation is known, but it says nothing whatsoever about the order in
which the operands are evaluated. Compiler can, and do, evaluate
operands in various orders. In fact, a common strategy is to evaluate
the most complex operand first.
I know that modifying a value multiple times between sequence points
results in UB, I don't think evaluating something multiple times
(without modifying it multiple times) is a problem.


It is if there is at least one modification and the other evaluations
aren't "read only to determine the value to be stored" (6.5p2).

-Larry Jones

There's a connection here, I just know it. -- Calvin
Mar 19 '06 #59
la************@ugs.com opined:
Vladimir S. Oka <no****@btopenworld.com> wrote:

la************@ugs.com opined:

It's a bit more complicated than that. First, the top-level
assignment expression (p = p->next = q) is evaluated. That
requires evaluating the left side (p) to determine the location to
store into and evaluating the right side (p->next = q) to determine
the value to
store. Those evaluations can occur in either order.
I admit that the normative text of the standard does allow (but not
mandate) such behaviour. However, as I have pointed earlier, the
Example 2 (non-normative, as examples are) suggests that the order
of evaluation is right-to-left.


No, it most certainly does not. Example 2 is primarily concerned
with the result type of assignment expressions, not order of
evaluation. About the only thing that it implies about order of
evaluation is that an operator's operands must be evaluated before
the final result of the operation is known, but it says nothing
whatsoever about the order in
which the operands are evaluated.


So, according to what you just said, in order to execute:

p = p->next = q;

the right assignment has to be done first. Otherwise, the final result
is not known and the left assignment cannot happen. Hence, the right
one must be executed first, QED. Executing the right assignment does
not modify `p`, so there's no multiple modifications between sequence
points, and no UB (`p` is modified once, and `p->next` is modified
once -- that's it).
Compiler can, and do, evaluate
operands in various orders. In fact, a common strategy is to
evaluate the most complex operand first.
I know that modifying a value multiple times between sequence points
results in UB, I don't think evaluating something multiple times
(without modifying it multiple times) is a problem.


It is if there is at least one modification and the other evaluations
aren't "read only to determine the value to be stored" (6.5p2).


--
BR, Vladimir

Bubble Memory, n.:
A derogatory term, usually referring to a person's
intelligence. See also "vacuum tube".

Mar 19 '06 #60
On 2006-03-19, Vladimir S. Oka <no****@btopenworld.com> wrote:
la************@ugs.com opined:
Vladimir S. Oka <no****@btopenworld.com> wrote:

la************@ugs.com opined:

It's a bit more complicated than that. First, the top-level
assignment expression (p = p->next = q) is evaluated. That
requires evaluating the left side (p) to determine the location to
store into and evaluating the right side (p->next = q) to determine
the value to
store. Those evaluations can occur in either order.

I admit that the normative text of the standard does allow (but not
mandate) such behaviour. However, as I have pointed earlier, the
Example 2 (non-normative, as examples are) suggests that the order
of evaluation is right-to-left.


No, it most certainly does not. Example 2 is primarily concerned
with the result type of assignment expressions, not order of
evaluation. About the only thing that it implies about order of
evaluation is that an operator's operands must be evaluated before
the final result of the operation is known, but it says nothing
whatsoever about the order in
which the operands are evaluated.


So, according to what you just said, in order to execute:

p = p->next = q;

the right assignment has to be done first. Otherwise, the final result
is not known and the left assignment cannot happen. Hence, the right
one must be executed first, QED. Executing the right assignment does
not modify `p`, so there's no multiple modifications between sequence
points, and no UB (`p` is modified once, and `p->next` is modified
once -- that's it).


That sounds right.

[No-one has claimed that "p = p->next" alone is UB, and I don't see what
this adds that would be]
Mar 19 '06 #61

Vladimir S. Oka wrote:
en******@yahoo.com opined:

Vladimir S. Oka wrote:
en******@yahoo.com opined:

>
> Vladimir S. Oka wrote:
>> On Friday 17 March 2006 15:27, en******@yahoo.com opined (in
>> <11**********************@j52g2000cwj.googlegroups .com>):
>>
>> >
>> > Vladimir S. Oka wrote:
>> >> On Friday 17 March 2006 04:48, en******@yahoo.com opined
>> >> (in
>> >> <11*********************@i39g2000cwa.googlegroups. com>):
>> >>
>> >> >
>> >> > pete wrote:
>> >> >> en******@yahoo.com wrote:
>> >> >> >
>> >> >> > Micah Cowan wrote:
>> >> >> > > Michael Mair <Mi**********@invalid.invalid> writes:
>> >> >> > >
>> >> >> > > > Richard G. Riley schrieb:
>> >> >> > > > > On 2006-03-12, pete <pf*****@mindspring.com>
>> >> >> > > > > wrote:
>> >> >> > > > >
>> >> >> > > > >> I'm coming around to thinking that 6.5 [#2] is
>> >> >> > > > >> relevant, and that p = p->next = q
>> >> >> > > > >>is undefined, and not just unspecified.
>> >> >> > > > > but
>> >> >> > > > > p=(p->next=q);
>> >> >> > > > > is fine? I hope .
>> >> >> > > >
>> >> >> > > > No. Whether you write
>> >> >> > > > a = b = c;
>> >> >> > > > or
>> >> >> > > > a = (b = c);
>> >> >> > > > does not change anything -- apart from clarifying
>> >> >> > > > your intent. You still are modifying p twice
>> >> >> > > > between sequence points
>> >> >> > >
>> >> >> > > Well, no he's not.
>> >> >> > > But he's reading its prior value for purposes other
>> >> >> > > than to determine the value stored, so same deal.
>> >> >> >
>> >> >> > Look again. Reading p is necessary to evaluate p->q
>> >> >> > = next,
>> >> >>
>> >> >> No, it isn't.
>> >> >> The value of (p->q = next) is (next)
>> >> >
>> >> > The value of p->q = next is next. But in order to get
>> >> > the value, the assignment p->q = next must _have been
>> >> > evaluated_, which needed both operands. Evaluation
>> >> > includes all the actions in the Semantics paragraph,
>> >> > which includes starting the side effect of storing the
>> >> > value.
>> >>
>> >> I think pete is right. The compiler _knows_ that the
>> >> result of (p->q = next) _will_be_ next before it even
>> >> produces any code, and can use that knowledge once it does
>> >> get to producing some.
>> >
>> > You've fallen into the trap of arguing based on what a
>> > compiler might be capable of. Regardless of what the
>> > compiler knows, it's still obliged to produce code that
>> > behaves according to how the Semantics paragraphs and
>> > everything else in the standard says it must.
>>
>> But it still does not evaluate p->q in order to assign next
>> to it. What is evaluated is next, and its value is /assigned/
>> to p->q. Next, the assignment is evaluated and assigned to p.
>> The assignment evaluates to next, but I don't think that
>> compiler is obliged to do that in any particular way.
>
> Sorry, the compiler _is_ obliged to do the evaluation as per
> the Semantics description. The Semantics paragraphs in 6.5.16
> specify _both_ that the store happens and what the value is.
> (Yes, the side effect of the store may happen later.) Where
> in the standard is there any statement that says an expression
> (_any_ expression) may yield a value _before_ it has been
> evaluated?

Ok, now my head starts to spin a bit, but bear with me...

Is it right that the original problem statement was:

p = p->next = q;


Yes.
Assuming it was: `p` is not modified twice, it is read once to
get `next`, and modified once to assign value to it in the
leftmost assignment. Assigning value to `next` does not modify
`p`, right?

Now, I re-read what 6.5.16 has to say, and yes, I know examples
are not normative, but to me Example 2 (6.5.16.1p5) seems to
support the following interpretation of the above statement:

1) `q` is evaluated
2) its value is assigned to `p->next`
3) that value becomes the value of the rightmost assignment
4) that value is assigned to `p`

I read that it happens in the order I give above. Also, `p` is
modified only once (4), and read only once (2).


Yes. Also the side effect of updating the value of p->next
can happen any time after (2), and the side effect of updating
the value of p can happen any time after (4).


I agree.

However, what is the side effect of updating `p->next`? It's just plain
storing a value into a variable. Again, `p` is not modified, AFAICT.
It's the struct member `next` that is, and `p` is just read to get its
address (`next`'s address).

Whether there's any side effect of updating `p` after (4) is, IMO,
irrelevant to the discussion (again, I can't see any side effect of
storing a value into variable).

I still think the operation in this case has to be equivalent to:

p->next = q;
p = p->next;


Right. Except the last part is better written as

t = q;
p->next = t;
p = t;

Mar 19 '06 #62

la************@ugs.com wrote:
Vladimir S. Oka <no****@btopenworld.com> wrote:

Now, I re-read what 6.5.16 has to say, and yes, I know examples
are not normative, but to me Example 2 (6.5.16.1p5) seems to
support the following interpretation of the above statement:

1) `q` is evaluated
2) its value is assigned to `p->next`
3) that value becomes the value of the rightmost assignment
4) that value is assigned to `p`


It's a bit more complicated than that. First, the top-level assignment
expression (p = p->next = q) is evaluated. That requires evaluating the
left side (p) to determine the location to store into and evaluating the
right side (p->next = q) to determine the value to store. Those
evaluations can occur in either order. ...


Why do you say the top level expression is evaluated
first? It makes more sense to say that subexpressions
(including simple operands) are evaluated first, and a
larger containing expression is evaluated only after
its operand subexpressions have been evaluated.

Mar 20 '06 #63

la************@ugs.com wrote:
Vladimir S. Oka <no****@btopenworld.com> wrote:

la************@ugs.com opined:

It's a bit more complicated than that. First, the top-level
assignment expression (p = p->next = q) is evaluated. That requires
evaluating the left side (p) to determine the location to store into
and evaluating the right side (p->next = q) to determine the value to
store. Those evaluations can occur in either order.


I admit that the normative text of the standard does allow (but not
mandate) such behaviour. However, as I have pointed earlier, the
Example 2 (non-normative, as examples are) suggests that the order of
evaluation is right-to-left.


No, it most certainly does not. Example 2 is primarily concerned with
the result type of assignment expressions, not order of evaluation.
About the only thing that it implies about order of evaluation is that
an operator's operands must be evaluated before the final result of the
operation is known, but it says nothing whatsoever about the order in
which the operands are evaluated. Compiler can, and do, evaluate
operands in various orders. In fact, a common strategy is to evaluate
the most complex operand first.


When asked about evaluation order by a beginner,
try saying this:

Precedence _does_ determine order of evaluation
for operATORS, but _doesn't_ determine order of
evaluation for operANDS.

Of course, it isn't completely accurate (because
of &&, etc), but usually after hearing that one
sentence the lights will go on.

Mar 20 '06 #64
Jordan Abel wrote:
On 2006-03-19, Vladimir S. Oka <no****@btopenworld.com> wrote:
la************@ugs.com opined:
Vladimir S. Oka <no****@btopenworld.com> wrote:
la************@ugs.com opined:
> It's a bit more complicated than that. First, the top-level
> assignment expression (p = p->next = q) is evaluated. That
> requires evaluating the left side (p) to determine the location to
> store into and evaluating the right side (p->next = q) to determine
> the value to
> store. Those evaluations can occur in either order.
I admit that the normative text of the standard does allow (but not
mandate) such behaviour. However, as I have pointed earlier, the
Example 2 (non-normative, as examples are) suggests that the order
of evaluation is right-to-left.
No, it most certainly does not. Example 2 is primarily concerned
with the result type of assignment expressions, not order of
evaluation. About the only thing that it implies about order of
evaluation is that an operator's operands must be evaluated before
the final result of the operation is known, but it says nothing
whatsoever about the order in
which the operands are evaluated.

So, according to what you just said, in order to execute:

p = p->next = q;

the right assignment has to be done first. Otherwise, the final result
is not known and the left assignment cannot happen. Hence, the right
one must be executed first, QED. Executing the right assignment does
not modify `p`, so there's no multiple modifications between sequence
points, and no UB (`p` is modified once, and `p->next` is modified
once -- that's it).


That sounds right.

[No-one has claimed that "p = p->next" alone is UB, and I don't see what
this adds that would be]


The problem with "p = p->next = q" is that wither the new or the old
value of p could be used to decide where to write q to. Regardless of
whether that is a real problem, there is also section 6.5 para 2 which says:
| 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.

Note the second sentence. In "p = p->next = q" p is read to determine
where to store q, and this violates the shall in the second sentence.
Unless, of course, evaluating p->next is part of determining the value
to be assigned to p...

Personally I don't like the line even if it is defined behaviour.
--
Flash Gordon, living in interesting times.
Web site - http://home.flash-gordon.me.uk/
comp.lang.c posting guidelines and intro:
http://clc-wiki.net/wiki/Intro_to_clc
Mar 20 '06 #65
Flash Gordon opined:
Jordan Abel wrote:
On 2006-03-19, Vladimir S. Oka <no****@btopenworld.com> wrote:
la************@ugs.com opined:

Vladimir S. Oka <no****@btopenworld.com> wrote:
> la************@ugs.com opined:
>> It's a bit more complicated than that. First, the top-level
>> assignment expression (p = p->next = q) is evaluated. That
>> requires evaluating the left side (p) to determine the location
>> to store into and evaluating the right side (p->next = q) to
>> determine the value to
>> store. Those evaluations can occur in either order.
> I admit that the normative text of the standard does allow (but
> not mandate) such behaviour. However, as I have pointed earlier,
> the Example 2 (non-normative, as examples are) suggests that the
> order of evaluation is right-to-left.
No, it most certainly does not. Example 2 is primarily concerned
with the result type of assignment expressions, not order of
evaluation. About the only thing that it implies about order of
evaluation is that an operator's operands must be evaluated before
the final result of the operation is known, but it says nothing
whatsoever about the order in
which the operands are evaluated.
So, according to what you just said, in order to execute:

p = p->next = q;

the right assignment has to be done first. Otherwise, the final
result is not known and the left assignment cannot happen. Hence,
the right one must be executed first, QED. Executing the right
assignment does not modify `p`, so there's no multiple
modifications between sequence points, and no UB (`p` is modified
once, and `p->next` is modified once -- that's it).
That sounds right.

[No-one has claimed that "p = p->next" alone is UB, and I don't see
[what
this adds that would be]


The problem with "p = p->next = q" is that wither the new or the old
value of p could be used to decide where to write q to. Regardless of
whether that is a real problem, there is also section 6.5 para 2
which says:
| 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.

Note the second sentence. In "p = p->next = q" p is read to determine
where to store q, and this violates the shall in the second sentence.
Unless, of course, evaluating p->next is part of determining the
value to be assigned to p...


Which was my point all along, and why I think it's OK.
Personally I don't like the line even if it is defined behaviour.


I do heartily agree with this. It's just that I think it is.

--
BR, Vladimir

Fourth Law of Revision:
It is usually impractical to worry beforehand about
interferences -- if you have none, someone will make one for you.

Mar 20 '06 #66
Vladimir S. Oka <no****@btopenworld.com> wrote:

Executing the right assignment does
not modify `p`, so there's no multiple modifications between sequence
points, and no UB (`p` is modified once, and `p->next` is modified
once -- that's it).


That's not correct. Since p is modified, it can be read "only to
determine the value to be stored". If it is read for any other reason,
the behavior is undefined. So, the crux of the matter is whether the
read of p in the embedded assignment (p->next = q) is "only to determine
the value to be stored" in p by the outer assignment or not. Many
people have argued that it is not (it's being read to determine where to
store q) and that's where the undefined behavior comes from.

For what it's worth, I believe the standard can be read either way. I
also believe that all of the formal sequence point models that have been
proposed make it well defined. I also believe there is at least one
implementation that gets it wrong.

-Larry Jones

I don't see why some people even HAVE cars. -- Calvin
Mar 20 '06 #67
en******@yahoo.com wrote:

Why do you say the top level expression is evaluated
first?
Because it is.
It makes more sense to say that subexpressions
(including simple operands) are evaluated first, and a
larger containing expression is evaluated only after
its operand subexpressions have been evaluated.


It's the evaluation of the top-level expression that causes the operand
subexpressions to be evaluated. This is particularly important for
cases where certain operands are *not* evaluated, such as in &&, ||, and
?: expressions.

-Larry Jones

I sure wish I could get my hands on some REAL dynamite. -- Calvin
Mar 20 '06 #68
la************@ugs.com opined:
Vladimir S. Oka <no****@btopenworld.com> wrote:

Executing the right assignment does
not modify `p`, so there's no multiple modifications between
sequence points, and no UB (`p` is modified once, and `p->next` is
modified once -- that's it).
That's not correct. Since p is modified, it can be read "only to
determine the value to be stored". If it is read for any other
reason, the behavior is undefined. So, the crux of the matter is
whether the read of p in the embedded assignment (p->next = q) is
"only to determine the value to be stored" in p by the outer
assignment or not. Many people have argued that it is not (it's
being read to determine where to store q) and that's where the
undefined behavior comes from.


That sounds reasonable enough. I'd still argue that `p` is read only to
determine the value to be stored. For me, the fact that reading it is
first used to figure out where to store `q` is just part of
determining what to finally store in `p`.

Count me in the (not so many?) other people, and let's agree to
disagree. Especially since you won't see me using such a construct
anyway.

:-)
For what it's worth, I believe the standard can be read either way.
I also believe that all of the formal sequence point models that have
been proposed make it well defined. I also believe there is at least
one implementation that gets it wrong.


I actually haven't tried this on any implementations. It's entirely
possible that some behave differently to the others, given differences
in opinions on this one.

--
BR, Vladimir

If you are over 80 years old and accompanied
by your parents, we will cash your check.

Mar 21 '06 #69
"Vladimir S. Oka" wrote:
la************@ugs.com opined:
.... snip ...
For what it's worth, I believe the standard can be read either
way. I also believe that all of the formal sequence point models
that have been proposed make it well defined. I also believe
there is at least one implementation that gets it wrong.


I actually haven't tried this on any implementations. It's
entirely possible that some behave differently to the others,
given differences in opinions on this one.


I think you are talking about "p = p->next = q;" constructs. The
"p = p->next" part is a very standard way of advancing down a
linked list, and the whole statement is a very normal way of
extending the list and advancing.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
Also see <http://www.safalra.com/special/googlegroupsreply/>
Mar 21 '06 #70
CBFalconer opined:
"Vladimir S. Oka" wrote:
la************@ugs.com opined:

... snip ...
For what it's worth, I believe the standard can be read either
way. I also believe that all of the formal sequence point models
that have been proposed make it well defined. I also believe
there is at least one implementation that gets it wrong.


I actually haven't tried this on any implementations. It's
entirely possible that some behave differently to the others,
given differences in opinions on this one.


I think you are talking about "p = p->next = q;" constructs. The
"p = p->next" part is a very standard way of advancing down a
linked list, and the whole statement is a very normal way of
extending the list and advancing.


Correct. That's what the whole discussion was about.

--
BR, Vladimir

A successful tool is one that was used to do something
undreamed of by its author.
-- S.C. Johnson

Mar 21 '06 #71
Vladimir S. Oka <no****@btopenworld.com> wrote:
[re. p = p->next = q;]

la************@ugs.com opined:

That's not correct. Since p is modified, it can be read "only to
determine the value to be stored". If it is read for any other
reason, the behavior is undefined. So, the crux of the matter is
whether the read of p in the embedded assignment (p->next = q) is
"only to determine the value to be stored" in p by the outer
assignment or not. Many people have argued that it is not (it's
being read to determine where to store q) and that's where the
undefined behavior comes from.
That sounds reasonable enough. I'd still argue that `p` is read only to
determine the value to be stored. For me, the fact that reading it is
first used to figure out where to store `q` is just part of
determining what to finally store in `p`.


For what it's worth, I and, I think, most, if not all, of the other
members of the C Standards committee agree with that interpretation,
which is why the formal models of sequence points all make the behavior
well-defined in this case. I think the intended interpretation is that
any reads must be in the context of evaluating the value to be stored,
not that they must directly affect the value. That would make well-
defined even somewhat ludicrous expressions like:

p = (p->prev = q->prev, p->next = q);
Count me in the (not so many?) other people, and let's agree to
disagree. Especially since you won't see me using such a construct
anyway.
We don't disagree, and I think we're actually in the majority. But
there is a vocal minority(?) that disagrees, and that disagreement isn't
without justification, which I why I felt the need to discuss it.
I actually haven't tried this on any implementations. It's entirely
possible that some behave differently to the others, given differences
in opinions on this one.


Most implementations get it right. I've only seen one report of an
implementation that gets it wrong.

-Larry Jones

No one can prove I did that!! -- Calvin
Mar 21 '06 #72

la************@ugs.com wrote:
en******@yahoo.com wrote:

Why do you say the top level expression is evaluated
first?


Because it is.


A non-answer answer. Bravo.
It makes more sense to say that subexpressions
(including simple operands) are evaluated first, and a
larger containing expression is evaluated only after
its operand subexpressions have been evaluated.


It's the evaluation of the top-level expression that causes the operand
subexpressions to be evaluated. This is particularly important for
cases where certain operands are *not* evaluated, such as in &&, ||, and
?: expressions.


The Semantics paragraphs for && and so forth give constraints
on which, whether, and in what order their subexpressions are
evaluated, but don't say anything about causality or whether
subexpression evaluation is done before or after evaluation of
the operator. So it sounds like you're just expressing a
personal viewpoint.

Mar 23 '06 #73

la************@ugs.com wrote:
Vladimir S. Oka <no****@btopenworld.com> wrote:

Executing the right assignment does
not modify `p`, so there's no multiple modifications between sequence
points, and no UB (`p` is modified once, and `p->next` is modified
once -- that's it).


That's not correct. Since p is modified, it can be read "only to
determine the value to be stored". ...


That sentence in the standard deserves a Lifetime Achievement
award in the DR Hall of Fame. Besides being vague about what
"only" quantifies and what constitutes an access "to determine
the value to be stored", there is the nonsense about undefined
behavior when an access is done as part of determining the
lvalue of which object to modify. What an absurdity! Like
it's possible for a value to be stored before the calculation
is made for where to store it... For extra hilarity, read Doug
Gwyn's defense of LHS-access causing UB because it's needed for
optimizing compilers on vector processors. The committee
should just admit they made a mistake in kowtowing to
freewheeling compiler vendors who can't be bothered to write
compilers that generate correct code. Clearly it would have
been better to add an advisory ala' restrict that allows the
more aggressive optimizations where the programmer explicitly
says it's okay.

Mar 23 '06 #74
Robin Haigh wrote:

"pete" <pf*****@mindspring.com> wrote in message
news:44***********@mindspring.com...
Robin Haigh wrote:
Trouble is, an enthusiastic reading of 6.5/2 can make all
sorts of things UB, including *p++.


An enthusiastic reading of 6.5/2 should find the footnote:

70)
This paragraph renders undefined statement expressions such as
i = ++i + 1;
a[i++] = i;
while allowing
i = i + 1;
a[i] = i;


Can you see how this footnote helps? I can't


It should clear up that *p++ is defined.
How do you figure that *p++ can be considered to be undefined
according to 6.5/2?

--
pete
Mar 23 '06 #75
en******@yahoo.com wrote:

la************@ugs.com wrote:

That's not correct. Since p is modified, it can be read "only to
determine the value to be stored". ...
That sentence in the standard deserves a Lifetime Achievement
award in the DR Hall of Fame.


Indeed. The problem is that it's extremely difficult to express the
intent precisely in English, which is why there is so much interest in a
formal model of sequence points that would do so. Unfortunately, there
hasn't been quite enough interest to succeed in doing so yet.
The committee
should just admit they made a mistake in kowtowing to
freewheeling compiler vendors who can't be bothered to write
compilers that generate correct code.


They didn't (kowtow to freewheeling vendors), they just tried to strike
a balance between performance and determinancy. High performance is
very important to most users of C, but getting the wrong answer isn't of
any use to anyone. Like I said before, I think most experienced C
programmers have an intuitive understanding of what kinds of things
should be well defined (and "p = p->next = q;" falls into that category)
and what kinds of things should be undefined (like "j = ++i + i;"), and
the formal models proposed so far, although still works in progress,
seem to match most people's intuition.

-Larry Jones

Even if lives DID hang in the balance, it would depend on whose they were.
-- Calvin
Mar 24 '06 #76

"pete" <pf*****@mindspring.com> wrote in message
news:44***********@mindspring.com...
Robin Haigh wrote:

"pete" <pf*****@mindspring.com> wrote in message
news:44***********@mindspring.com...
Robin Haigh wrote:

> Trouble is, an enthusiastic reading of 6.5/2 can make all
> sorts of things UB, including *p++.

An enthusiastic reading of 6.5/2 should find the footnote:

70)
This paragraph renders undefined statement expressions such as
i = ++i + 1;
a[i++] = i;
while allowing
i = i + 1;
a[i] = i;


Can you see how this footnote helps? I can't


It should clear up that *p++ is defined.
How do you figure that *p++ can be considered to be undefined
according to 6.5/2?


I don't. I've only said that this is the logical conclusion of the claim
made by others in previous threads, namely that the value of p may not be
used for any other purpose than computing its new value.

The footnote doesn't clarify because it doesn't show an allowed example
containing a post-increment. In fact the undefined example a[i++] = i
contains 3 uses of i:
(1) to compute the new value of i
(2) to determine which element of a is modified
(3) to determine the new value of that element
and the contrasted example a[i] = i contains uses 2 and 3, from which one
might paradoxically deduce that use 1 must be the problem. (This is of
course a spot-the-fallacy exercise)

As I said, a line has to be drawn, so that we know what is undefined and
what isn't. The line must be somewhere between the allowed examples and the
undefined examples, but the gap is quite wide and a number of things fall in
the middle. To draw the line, all we can do is try to determine the
intended meaning of the wording. Various readings are possible, but not all
are sustainable.

I suppose it all depends on your tolerance for contradiction. The ability
to believe arguments whose logical consequences are untenable is one of the
peculiarities of the human condition.

--
RSH

Mar 24 '06 #77

la************@ugs.com wrote:
en******@yahoo.com wrote:

la************@ugs.com wrote:

That's not correct. Since p is modified, it can be read "only to
determine the value to be stored". ...


That sentence in the standard deserves a Lifetime Achievement
award in the DR Hall of Fame.


Indeed. The problem is that it's extremely difficult to express the
intent precisely in English, which is why there is so much interest in a
formal model of sequence points that would do so. Unfortunately, there
hasn't been quite enough interest to succeed in doing so yet.


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 in
subexpressions of the operator causing the modification.
The committee
should just admit they made a mistake in kowtowing to
freewheeling compiler vendors who can't be bothered to write
compilers that generate correct code.


They didn't (kowtow to freewheeling vendors), they just tried to strike
a balance between performance and determinancy. High performance is
very important to most users of C, but getting the wrong answer isn't of
any use to anyone. Like I said before, I think most experienced C
programmers have an intuitive understanding of what kinds of things
should be well defined (and "p = p->next = q;" falls into that category)
and what kinds of things should be undefined (like "j = ++i + i;"), and
the formal models proposed so far, although still works in progress,
seem to match most people's intuition.


The problem isn't the things people think will work and do, but
the things experienced people think should work and don't. The
idea that reading the prior value as part of calculating the
store-lvalue be undefined behavior is just stupid. Doug Gwyn
kept talking about vectorizing compilers, but he never gave even
one example program. Dik Winter gave an example program (which
he admitted wasn't a bona fide example), but it clearly shows the
vectorizing compiler to be wrong, since one statement incorrectly
affects _another statement_ (ie, after a sequence point). Dik
Winter also gave some pseudo-assembly as an example, but the
assembly _re-evaluated_ a subexpression after something had been
modified. Not even remotely convincing. (The thread can be seen
in google groups, "strange behaviour with a[a[i]]".)

I'm all for having formal models and a standard that matches
people's intuition. Since all the formal models and everyone's
intuition say that using the prior value to calculate the lvalue
of where to store be defined, and arguments to the contrary are
hypothetical and weak at best, why was the concession made, if
not because the committee just gave in to the compiler vendors?
AFAIK no one has presented a single real-world example of an
implementation that benefits from this so-called "optimization".

Mar 25 '06 #78

This thread has been closed and replies have been disabled. Please start a new discussion.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.