473,785 Members | 2,794 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
en******@yahoo. com wrote:

Richard G. Riley wrote:
"en******@yahoo .com"posted the following on 2006-03-10:

Richard Heathfield wrote:
> be***@uwalumni. com said:
>
> > 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?
>
> The associativity is: a = (b = c); but the order of evaluation of a, b, and
> c is unspecified. The Standard only requires that the new values of a and b
> are provided at some time after the previous, and before the following,
> sequence point.
>
> So gcc is quite within its rights to compile it to: a = c; b = c; or b = c;
> a = c; or b = c; a = b; or tmp = c; a = tmp; b = tmp; or any other
> combination that gives the same result.
>
> If you depend on the order of evaluation, any side effects of a, b, and c
> are likely to bite you eventually.

You missed the point of his question. Regardless of anything having
to do with evaluation order, the intermediate assignment to b can
affect the value that is assigned to a. int = unsigned char = int,
for example. If b is volatile that may also change the picture,
as another thread discusses. It isn't safe to assume (because
it's open to debate) that a = b = c may be replaced by b = c, a = b
even if b is volatile. But saying a = b = c means (in whatever
order) a = c and b = c is simply wrong.


Why? If you write the code properly and a,b,c are the same types and
none of them are physically volative and this is a single thread app
then I think the code can indeed infer equality. If not then we might
as well give up.

If they are not the same types then without the right casts you have
no right coding like this IMO because of hiccups down the line when
someone less familiar with the code comes along.


Please try to pay attention. The question asked isn't about
whether a = b = c is good programming or whether anyone has
the "right" to use it in a program, but what the C Standard
says it means.


The point of interest is that
"assignment " is not a sequence point.

If
sorted -> next = *node;
sorted = *node;
is defined, then
sorted = sorted -> next = *node;
is undefined.
--
pete
Mar 11 '06 #11
Keith Thompson wrote:
Richard Heathfield <in*****@invali d.invalid> writes:
en******@yahoo. com said:
Please try to pay attention. The question asked isn't about
whether a = b = c is good programming or whether anyone has
the "right" to use it in a program, but what the C Standard
says it means.


You are Dan Pop, and I claim my five pounds!


A questionable assumption in the absence of the phrase "engage your
brain".


Chapter and verse please.

Nyuk nyuk.
Mark F. Haigh
mf*****@sbcglob al.net

Mar 11 '06 #12

Richard Heathfield wrote:
en******@yahoo. com said:

Richard Heathfield wrote:

If you depend on the order of evaluation, any side effects of a, b, and c
are likely to bite you eventually.


You missed the point of his question. Regardless of anything having
to do with evaluation order, the intermediate assignment to b can
affect the value that is assigned to a.


I invite you to re-read my reply, especially the bit about side effects
(retained above).


I invite you to read the OP's posting again, and also the
description of how assignment expressions work in section
6.5.16. Your comment may have given useful advice but
wasn't really addressing the question asked. My comment was
on point, and also correct (of course you snipped the part
that explains that).

Chris Torek gave the best answer, being both on point and
a good explanation of the various issues.

Mar 11 '06 #13

pete wrote:
en******@yahoo. com wrote:

Richard G. Riley wrote:
"en******@yahoo .com"posted the following on 2006-03-10:

>
> Richard Heathfield wrote:
>> be***@uwalumni. com said:
>>
>> > 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?
>>
>> The associativity is: a = (b = c); but the order of evaluation of a, b, and
>> c is unspecified. The Standard only requires that the new values of a and b
>> are provided at some time after the previous, and before the following,
>> sequence point.
>>
>> So gcc is quite within its rights to compile it to: a = c; b = c; or b = c;
>> a = c; or b = c; a = b; or tmp = c; a = tmp; b = tmp; or any other
>> combination that gives the same result.
>>
>> If you depend on the order of evaluation, any side effects of a, b, and c
>> are likely to bite you eventually.
>
> You missed the point of his question. Regardless of anything having
> to do with evaluation order, the intermediate assignment to b can
> affect the value that is assigned to a. int = unsigned char = int,
> for example. If b is volatile that may also change the picture,
> as another thread discusses. It isn't safe to assume (because
> it's open to debate) that a = b = c may be replaced by b = c, a = b
> even if b is volatile. But saying a = b = c means (in whatever
> order) a = c and b = c is simply wrong.
>

Why? If you write the code properly and a,b,c are the same types and
none of them are physically volative and this is a single thread app
then I think the code can indeed infer equality. If not then we might
as well give up.

If they are not the same types then without the right casts you have
no right coding like this IMO because of hiccups down the line when
someone less familiar with the code comes along.


Please try to pay attention. The question asked isn't about
whether a = b = c is good programming or whether anyone has
the "right" to use it in a program, but what the C Standard
says it means.


The point of interest is that
"assignment " is not a sequence point.

If
sorted -> next = *node;
sorted = *node;
is defined, then
sorted = sorted -> next = *node;
is undefined.


Even if that ridiculous claim were true, it isn't responsive
to the OP's question. Does the intermediate assignment
influence what value is assigned to a? The answer to that
is YES. Must the value that is written into b be read out
again to assign to a? The answer to that is NO (if b isn't
volatile) or MAYBE (if b is volatile). Sequence points are
an irrelevant side issue.

Mar 11 '06 #14

Richard G. Riley wrote:
"en******@yahoo .com"posted the following on 2006-03-10:

Richard G. Riley wrote:
"en******@yahoo .com"posted the following on 2006-03-10:

>
> Richard Heathfield wrote:
>> be***@uwalumni. com said:
>>
>> > 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?
>>
>> The associativity is: a = (b = c); but the order of evaluation of a, b, and
>> c is unspecified. The Standard only requires that the new values of a and b
>> are provided at some time after the previous, and before the following,
>> sequence point.
>>
>> So gcc is quite within its rights to compile it to: a = c; b = c; or b = c;
>> a = c; or b = c; a = b; or tmp = c; a = tmp; b = tmp; or any other
>> combination that gives the same result.
>>
>> If you depend on the order of evaluation, any side effects of a, b, and c
>> are likely to bite you eventually.
>
> You missed the point of his question. Regardless of anything having
> to do with evaluation order, the intermediate assignment to b can
> affect the value that is assigned to a. int = unsigned char = int,
> for example. If b is volatile that may also change the picture,
> as another thread discusses. It isn't safe to assume (because
> it's open to debate) that a = b = c may be replaced by b = c, a = b
> even if b is volatile. But saying a = b = c means (in whatever
> order) a = c and b = c is simply wrong.
>

Why? If you write the code properly and a,b,c are the same types and
none of them are physically volative and this is a single thread app
then I think the code can indeed infer equality. If not then we might
as well give up.

If they are not the same types then without the right casts you have
no right coding like this IMO because of hiccups down the line when
someone less familiar with the code comes along.


Please try to pay attention. The question asked isn't about
whether a = b = c is good programming or whether anyone has
the "right" to use it in a program, but what the C Standard
says it means.


Do pay attention : it moved on to the affects of volatility : and it
is this I was asking about. It was also discussing real world issues
at this stage and the "standard" was another issue. Pay particular
attention to my comments about using C in the real world in the
paragraph beginngin with "Why?" - as you will see, it was a question
and not a statement : a question to the a=c and b=c is simply wrong
statement.


Don't be an idiot. The only one talking about "real world
issues" was you. Any questions about whether something is
"physically volatile" or we are dealing with a "single
threaded app" are completely irrelevant to the original
question and to my comments. Whether or not any of the
variables is volatile, the intermediate assignment to b
influences the value assigned to a; read section 6.5.16.
And don't presume that other people's assumptions match
your assumptions. More often than you expect, they don't.

Mar 11 '06 #15
en******@yahoo. com said:

Chris Torek gave the best answer


That is always true.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Mar 11 '06 #16
Richard Heathfield <in*****@invali d.invalid> writes:
en******@yahoo. com said:

Chris Torek gave the best answer


That is always true.


The best that the rest of us can hope for is to answer a question
earlier than Chris, or to answer a question that he doesn't.
--
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 11 '06 #17
en******@yahoo. com wrote:

pete wrote:
en******@yahoo. com wrote:

Richard G. Riley wrote:
> "en******@yahoo .com"posted the following on 2006-03-10:
>
> >
> > Richard Heathfield wrote:
> >> be***@uwalumni. com said:
> >>
> >> > 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?
> >>
The point of interest is that
"assignment " is not a sequence point.

If
sorted -> next = *node;
sorted = *node;
is defined, then
sorted = sorted -> next = *node;
is undefined.
Even if that ridiculous claim were true,


The ridiculous claim is true.
The topic comes up on this newsgroup from time to time,
usually in the form of "p = p->next = q"
You can look it up next time you're online.

http://groups.google.com/group/comp....Enext+%3D+q%22

http://groups.google.com/group/comp....7e2102fd256d79

"The p = p->next = q problem is also a real problem that came from
a program I was writing when I posted a question about it here
years ago." -- Ben Pfaff
it isn't responsive
to the OP's question. Does the intermediate assignment
influence what value is assigned to a? The answer to that
is YES.


No.
The value of the intermediate assignment
influences what value is assigned to a,
but that value is known prior to the side effect
of the actual assignment taking place.

If you have
unsigned char uc;
unsigned int ui;
ui = uc = -1;
that can be translated as either
uc = UCHAR_MAX;
ui = UCHAR_MAX;
or
ui = UCHAR_MAX;
uc = UCHAR_MAX;
The order in which the side effects take place doesn't matter.

OP's question is entirely an issue of
side effects not being ordered between sequence points.

--
pete
Mar 11 '06 #18

pete wrote:
en******@yahoo. com wrote:

pete wrote:
en******@yahoo. com wrote:
>
> Richard G. Riley wrote:
> > "en******@yahoo .com"posted the following on 2006-03-10:
> >
> > >
> > > Richard Heathfield wrote:
> > >> be***@uwalumni. com said:
> > >>
> > >> > 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?
> > >> The point of interest is that
"assignment " is not a sequence point.

If
sorted -> next = *node;
sorted = *node;
is defined, then
sorted = sorted -> next = *node;
is undefined.
Even if that ridiculous claim were true,


The ridiculous claim is true.
The topic comes up on this newsgroup from time to time,
usually in the form of "p = p->next = q"
You can look it up next time you're online.

http://groups.google.com/group/comp....Enext+%3D+q%22

http://groups.google.com/group/comp....7e2102fd256d79

"The p = p->next = q problem is also a real problem that came from
a program I was writing when I posted a question about it here
years ago." -- Ben Pfaff


Excuse me while I stop laughing. 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). The same thing is true for
assignment: only the *side effect* of updating the object
being assigned might be delayed until the next sequence
point. And there's no point in allowing an "optimizati on"
which if it's allowed causes people to stop using the very
construct being optimized.

If it were permitted to evaluate operators before operands
when the resulting value is "known" then this code could get
undefined behavior -

unsigned u = 12345, *p = &u;
p += 1|(0&*p);

The idea that p = p->next = q is allowed to store into
p before evaluating p->next doesn't pass the laugh test.
it isn't responsive
to the OP's question. Does the intermediate assignment
influence what value is assigned to a? The answer to that
is YES.


No.
The value of the intermediate assignment
influences what value is assigned to a,
but that value is known prior to the side effect
of the actual assignment taking place.


The "intermedia te assignment" I'm talking about is the text
"b =", not any run time operation.
If you have
unsigned char uc;
unsigned int ui;
ui = uc = -1;
that can be translated as either
uc = UCHAR_MAX;
ui = UCHAR_MAX;
or
ui = UCHAR_MAX;
uc = UCHAR_MAX;
The order in which the side effects take place doesn't matter.

OP's question is entirely an issue of
side effects not being ordered between sequence points.


If you think that then you didn't understand the question
the OP was trying to ask.

Mar 12 '06 #19
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?
--
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 #20

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.