473,785 Members | 2,807 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 4759
Ben Pfaff wrote:

en******@yahoo. com writes:
Any compiler that compiles p = p->next = q as storing into p
before fetching p->next is simply broken. Operands are
evaluated before the operator they're operands for, and
operators are evaluated before they produce a value--that's
just how C semantics work (in a C abstract machine of course).


Do you have any citations to back up your assertions?


I think he's confused about sequence points.
Some of the standard's function operator descriptions
seem to order the sequence of events between sequence points,
without proper respect to the concept of sequence points.

Here, we see the standard claim that the postfix increment
takes place after the result is obtained:
N869
6.5.2.4 Postfix increment and decrement operators
[#2] The result of the postfix ++ operator is the value of
the operand. After the result is obtained, the value of the
operand is incremented.

But, if we look at
N869
5.1.2.3 Program execution
[#16] EXAMPLE 7
"sum = (((sum * 10) - '0') + ((*(p++)) = (getchar())));
but the actual increment of p can occur at any time between
the previous sequence point and the next sequence point "

.... we see the standard deny any ordering of events
between sequence points.

In the p = p->next = q thread discussion, a lot of people quoted:
N869
6.5 Expressions
[#2] Furthermore, the prior value
shall be accessed only to determine the value to be
stored.60)
60)This paragraph renders undefined statement expressions
such as
i = ++i + 1;
a[i++] = i;
while allowing
i = i + 1;
a[i] = i;

.... but I don't think that's really what makes the case for
undefinedness,
because that would imply that there is something wrong with
p = p->next
and I don't think that there is anything wrong with
p = p->next

I think it's just simply that assignments aren't sequence points,
which is what the problem is with
p = p->next = q.

--
pete
Mar 12 '06 #21
pete wrote:
In the p = p->next = q thread discussion, a lot of people quoted:
N869
6.5 Expressions
[#2] Furthermore, the prior value
shall be accessed only to determine the value to be
stored.60)
60)This paragraph renders undefined statement expressions
such as
i = ++i + 1;
a[i++] = i;
while allowing
i = i + 1;
a[i] = i;

... but I don't think that's really what makes the case for
undefinedness,
because that would imply that there is something wrong with
p = p->next
and I don't think that there is anything wrong with
p = p->next

I think it's just simply that assignments aren't sequence points,
which is what the problem is with
p = p->next = q.


I've been mulling this, and I've come to think that my
p = p->next
implication, is incorrect.
In the multiple assignment expression, "the prior value", (p),
is also accessed to determine which object
is the lvalue in the assignment from q
p->next = q

I'm coming around to thinking that 6.5 [#2] is relevant, and that
p = p->next = q
is undefined, and not just unspecified.

--
pete
Mar 12 '06 #22
On 2006-03-12, pete <pf*****@mindsp ring.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 .
Mar 12 '06 #23
Richard G. Riley schrieb:
On 2006-03-12, pete <pf*****@mindsp ring.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; parentheses
do not introduce new sequence points.
If you want to be on the safe side, you can only do
p->next = q, p = p->next;
which IMO does not give you any advantage over
p->next = q;
p = p->next;

Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Mar 12 '06 #24
"Richard G. Riley" <rg****@gmail.c om> writes:
On 2006-03-12, pete <pf*****@mindsp ring.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 .


Why would you think it to be any different? Parentheses do not
insert a sequence point.
--
Just another C hacker.
Mar 12 '06 #25
On 2006-03-12, Michael Mair <Mi**********@i nvalid.invalid> wrote:
Richard G. Riley schrieb:
On 2006-03-12, pete <pf*****@mindsp ring.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; parentheses
do not introduce new sequence points.
If you want to be on the safe side, you can only do
p->next = q, p = p->next;
which IMO does not give you any advantage over
p->next = q;
p = p->next;

Cheers
Michael


Well, thats a shit load of legacy code I didnt properly break down
then. Mind you, I'm sure there was never a problem.

I'm truly astonished at this.

But looking at it anyway its not quite as "common" as

a=b=c=1;

Whats the problem with the above? Anything? (Assuming single thread
etc).

Mar 12 '06 #26
"Richard G. Riley" <rg****@gmail.c om> writes:
a=b=c=1;

Whats the problem with the above?


Nothing. It's fine.
--
int main(void){char p[]="ABCDEFGHIJKLM NOPQRSTUVWXYZab cdefghijklmnopq rstuvwxyz.\
\n",*q="kl BIcNBFr.NKEzjwC IxNJC";int i=sizeof p/2;char *strchr();int putchar(\
);while(*q){i+= strchr(p,*q++)-p;if(i>=(int)si zeof p)i-=sizeof p-1;putchar(p[i]\
);}return 0;}
Mar 12 '06 #27

"pete" <pf*****@mindsp ring.com> wrote in message
news:44******** ***@mindspring. com...
Ben Pfaff wrote:

en******@yahoo. com writes:
Any compiler that compiles p = p->next = q as storing into p
before fetching p->next is simply broken. Operands are
evaluated before the operator they're operands for, and
operators are evaluated before they produce a value--that's
just how C semantics work (in a C abstract machine of course).


Do you have any citations to back up your assertions?


I think he's confused about sequence points.
Some of the standard's function operator descriptions
seem to order the sequence of events between sequence points,
without proper respect to the concept of sequence points.

Here, we see the standard claim that the postfix increment
takes place after the result is obtained:
N869
6.5.2.4 Postfix increment and decrement operators
[#2] The result of the postfix ++ operator is the value of
the operand. After the result is obtained, the value of the
operand is incremented.

But, if we look at
N869
5.1.2.3 Program execution
[#16] EXAMPLE 7
"sum = (((sum * 10) - '0') + ((*(p++)) = (getchar())));
but the actual increment of p can occur at any time between
the previous sequence point and the next sequence point "

... we see the standard deny any ordering of events
between sequence points.

But the standard isn't just a collection of sayings to be quoted out of
context. You have to follow the narrative.

The first quote here is defining the semantics of the abstract machine.

The second quote occurs as part of a long discussion of the "as-if" rule,
i.e. the extent to which an implementation may or may not depart from the
abstract machine.

The second quote doesn't contradict the first. On the contrary, it
presupposes the first: if the semantics of the abstract machine were
unspecified, there wouldn't be much point in saying that the real machine
has more latitude.

--
RSH
Mar 13 '06 #28
Michael Mair <Mi**********@i nvalid.invalid> writes:
Richard G. Riley schrieb:
On 2006-03-12, pete <pf*****@mindsp ring.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.
Mar 14 '06 #29
Micah Cowan schrieb:
Michael Mair <Mi**********@i nvalid.invalid> writes:

Richard G. Riley schrieb:
On 2006-03-12, pete <pf*****@mindsp ring.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.


You are right, thanks for the correction.

Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Mar 14 '06 #30

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.