473,770 Members | 2,104 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 #1
77 4755
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.

--
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 10 '06 #2
On 2006-03-10, be***@uwalumni. com <be***@uwalumni .com> wrote:
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.
If you do that, a sprinkling of the "volatile" keyword may do something
for predictability
He claims it has been a 'C Standard' that it will be evaluted as a =
c; b = c.
His interpretaion of the standard is the same as mine.
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?


Use volatile. You might still get the wrong answer, but it's more likely
to be consistent.
Mar 10 '06 #3

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.

Mar 10 '06 #4
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).

--
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 10 '06 #5

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.

Mar 10 '06 #6
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!
--
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 10 '06 #7
In article <11************ *********@j33g2 000cwa.googlegr oups.com>
<be***@uwalumni .com> wrote:
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. ...
Well, first, if you have not applied the "volatile" qualifier, you
have no right to expect anything in particular, because a compiler
(even without optimization turned on) is allowed to believe that
non-"volatile" objects behave as if they are ordinary RAM. That is,
if you store 3 in some "int", and do not store another value in that
"int", it will still have 3 in it later. So:

void f(void) {
int i = 3;
... /* code that does not modify i */
printf("i is %d\n", i);
...
}

could be compiled to the same object code as:

void f(void) {
... /* code that does not modify i */
puts("i is 3");
...
}

(note the removal of the newline, since puts() adds one; and yes,
gcc really will turn printf() calls into puts() calls in some
cases).
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 C89 and C99 standards both use similar (maybe even identical)
wording:

[#3] An assignment operator stores a value in the object
designated by the left operand. An assignment expression
has the value of the left operand after the assignment, but
is not an lvalue. The type of an assignment expression is
the type of the left operand unless the left operand has
qualified type, in which case it is the unqualified version
of the type of the left operand. The side effect of
updating the stored value of the left operand shall occur
between the previous and the next sequence point.

The second sentence is particularly important here. It tells us
that, for instance, if we write:

unsigned int a;
unsigned char b;
unsigned int c = 12345;

a = b = c;

the result stored in "a" is almost certainly *not* 12345, as it is
actually (12345 % (UCHAR_MAX + 1)). Typically UCHAR_MAX is 255 so
this is (12345 % 256), or 57. Of course, the compiler can use the
"as-if" rules to compile this as:

a = 57;
b = 57;
c = 12345;

(with the stores to a, b, and c happening in any order in the
actual underlying machine code -- or even being combined, if
there is some quick way to write to two or all three variables).

In the more difficult example where "b" is somehow mapped to a
hardware register, you -- the programmer -- *must* declare b using
the "volatile" qualifier, to tell the compiler "this thing is *not*
ordinary RAM, so you, Mr Compiler, must not play games with
optimizations that assume it *is* ordinary RAM." More typically,
you might replace b with *p where p has type "volatile T *" for
some type T. Consider the example of a memory-mapped device
that has a control-and-status register, in which writes to the
location cause the device to take actions, and reads from the
location return the device's status:

#define CSR_W_DMA 0x01 /* start DMA */
#define CSR_W_LDA 0x02 /* load DMA address from addr reg */
#define CSR_W_EI 0x04 /* enable interrupts */
#define CSR_W_RD 0x08 /* read from device (write to RAM) */
#define CSR_W_WR 0x00 /* write to device (read from RAM) - pseudo */
...
#define CSR_S_DMA 0x01 /* DMA is occuring now */
#define CSR_S_ERR 0x02 /* error occurred doing DMA */
#define CSR_S_IP 0x04 /* interrupt pending / op done-or-failed */
...

volatile int *csr;
volatile int *addr;
...
*addr = dma_addr; /* tell device where to do the op */
*csr = CSR_W_LDA;

/* do read from device, without using interrupts (poll for done) */
*csr = CSR_W_RD | CSR_W_DMA; /* read op with DMA */
while ((*csr & CSR_W_IP) == 0)
continue;

Without the "volatile" qualifier, the compiler can remove the first
write to *csr entirely (because the next write to *csr clobbers
the previous one), and replace the while loop with one that never
terminates (because we did not set CSR_W_EI and CSR_W_IP is the
same bit, so obviously that bit will never turn on).

Note that on some hardware (SPARC V9 for instance), the CPU may
need special instructions inserted at various points. These
instructions may even depend on the memory model set in the CPU.
(In this case, if I remember right, at least one, maybe two, "membar
#StoreStore"s and/or a "membar #MemIssue" in RMO, nothing at all
in TSO, and just one "StoreStore " in PSO; this depends on the fact
that the CPU recognizes the same address for the reads and writes
of the CSR. If the status register had a different address, one
more membar would sometimes be required.)

See also the ongoing thread "Volatiles in assignment expressions".
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Mar 10 '06 #8
On 2006-03-10, Richard G. Riley <rg*****@gmail. com> wrote:
"Jordan"pos ted the following on 2006-03-10:
On 2006-03-10, be***@uwalumni. com <be***@uwalumni .com> wrote:
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.
If you do that, a sprinkling of the "volatile" keyword may do something
for predictability
He claims it has been a 'C Standard' that it will be evaluted as a =
c; b = c.


His interpretaion of the standard is the same as mine.
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?


Use volatile. You might still get the wrong answer, but it's more likely
to be consistent.


Could you explain how volatile changes anything here?


As far as I can tell, volatile restricts the compiler from making
optimizations that change the number or sense of accesses to the
variable in question.
It doesnt alter the limited bits in his memory mapped register and I
cant quite work out how it would make anything better : having said
that I only ever used volatile on HW port maps. Is that the issue
here? b is changing between "b=c" and "a=b"? Is this register a
read/write with some bits changing externally?
That's what the OP apparently says [i.e. some bits are changed to 0 at
the time of the write]
Then I see how volatile would work, but certainly wouldnt be using
a=b=c no matter what in this case.

Mar 10 '06 #9
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".

--
Keith Thompson (The_Other_Keit h) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Mar 11 '06 #10

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.