x=r=y; // With r volatile. Is r read?

Discussion in 'C Programming' started by Francois Grieu, Mar 7, 2011.

1. Francois GrieuGuest

Hi, the subject sums it all.

extern volatile unsigned r;
unsigned x,y;

void test(void)
{
x=r=y;
}

What happens:
- y is read, written in r and in x.
- y is read, written in r; then r is read, written in x.
- any of the above.
- other..

TIA,
Francois Grieu

Francois Grieu, Mar 7, 2011

2. Mark BluemelGuest

On 03/07/2011 04:05 PM, Francois Grieu wrote:
> Hi, the subject sums it all.
>
> extern volatile unsigned r;
> unsigned x,y;
>
> void test(void)
> {
> x=r=y;
> }
>
> What happens:
> - y is read, written in r and in x.
> - y is read, written in r; then r is read, written in x.
> - any of the above.
> - other..

My reading of this is that your statement is exactly equivalent
to "x=(r=y);".

That is to say that the value of the expression "r=y" is assigned to x -
so there is no need for r to be read.

Mark Bluemel, Mar 7, 2011

3. Francois GrieuGuest

On 07/03/2011 17:33, Mark Bluemel wrote:
> On 03/07/2011 04:05 PM, Francois Grieu
>> Hi, the subject sums it all.
>>
>> extern volatile unsigned r;
>> unsigned x,y;
>>
>> void test(void)
>> {
>> x=r=y;
>> }
>>
>> What happens:
>> - y is read, written in r and in x.
>> - y is read, written in r; then r is read, written in x.
>> - any of the above.
>> - other..

>
> My reading of this is that your statement is exactly equivalent
> to "x=(r=y);".

Yes.

> That is to say that the value of the expression "r=y" is assigned to x

Yes.

> so there is no need for r to be read.

I'm unsure of that, and of if "no need" translates to "no read".
My problem boils down to: is the value of (r=y)
- the value read from y (that gets written into r).
- the value read from r (after?) writing the value of y into r.
- any of the above.
- other..

Francois Grieu

Francois Grieu, Mar 7, 2011
4. Mark BluemelGuest

On 03/07/2011 04:41 PM, Francois Grieu wrote:
> On 07/03/2011 17:33, Mark Bluemel wrote:
>> On 03/07/2011 04:05 PM, Francois Grieu
>>> Hi, the subject sums it all.
>>>
>>> extern volatile unsigned r;
>>> unsigned x,y;
>>>
>>> void test(void)
>>> {
>>> x=r=y;
>>> }
>>>
>>> What happens:
>>> - y is read, written in r and in x.
>>> - y is read, written in r; then r is read, written in x.
>>> - any of the above.
>>> - other..

>>
>> My reading of this is that your statement is exactly equivalent
>> to "x=(r=y);".

>
> Yes.
>
>> That is to say that the value of the expression "r=y" is assigned to x

>
> Yes.
>
>> so there is no need for r to be read.

>
> I'm unsure of that, and of if "no need" translates to "no read".
> My problem boils down to: is the value of (r=y)
> - the value read from y (that gets written into r).
> - the value read from r (after?) writing the value of y into r.
> - any of the above.
> - other..

http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
6.5.16 paragraph 3
.... An assignment expression has the value of the left operand after the
assignment ....

I see no mention of other operations after the assignment.

Mark Bluemel, Mar 7, 2011
5. Guest

Francois Grieu <> wrote:
>
> My problem boils down to: is the value of (r=y)
> - the value read from y (that gets written into r).
> - the value read from r (after?) writing the value of y into r.
> - any of the above.

Any of the above. "What constitutes an access to an object that has
volatile-qualified type is implementation-defined." (6.7.3p7) The
implementation is permitted to read the value from r, but it is not
required to.
--
Larry Jones

I think grown-ups just ACT like they know what they're doing. -- Calvin

, Mar 7, 2011
6. JensGuest

On 7 Mrz., 20:33, wrote:
> Any of the above.  "What constitutes an access to an object that has
> volatile-qualified type is implementation-defined." (6.7.3p7)  The
> implementation is permitted to read the value from r, but it is not
> required to.

Exactly. The draft of C1X even has a footnote (in assignment
operators) to make the situation in question explicit:

C1X> The implementation is permitted to read the object to determine
the value but is not
C1X> required to, even when the object has volatile-qualified type.

Jens

Jens, Mar 7, 2011
7. Francois GrieuGuest

On 07/03/2011 22:42, Jens wote on my question <quote>
>>>> My problem boils down to: is the value of (r=y)
>>>> - the value read from y (that gets written into r).
>>>> - the value read from r (after?) writing the value of y into r.
>>>> - any of the above.
>>>> - other.. </quote>

>
> On 7 Mrz., 20:33, wrote:
>> Any of the above. "What constitutes an access to an object that has
>> volatile-qualified type is implementation-defined." (6.7.3p7) The
>> implementation is permitted to read the value from r, but it is not
>> required to.

>
> Exactly. The draft of C1X even has a footnote (in assignment
> operators) to make the situation in question explicit:
>
> C1X> The implementation is permitted to read the object to determine
> the value but is not
> C1X> required to, even when the object has volatile-qualified type.

Yes. Quoting <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1548.pdf>
more in depth:

" 6.5.16 Assignment operators (..)
p3) 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, (note 111) but is not an lvalue.
(..)

(111) The implementation is permitted to read the object to determine
the value but is not required to, even when the object has
volatile-qualified type. "

That settles (r=y) can have either
- the value read from y that also gets written into r
- the value read from r AFTER writing the value of y into r

Thanks.

Francois Grieu

Francois Grieu, Mar 8, 2011
8. NoobGuest

Francois Grieu wrote:

> extern volatile unsigned r;
> unsigned x,y;
>
> void test(void)
> {
> x=r=y;
> }
>
> What happens:
> - y is read, written in r and in x.
> - y is read, written in r; then r is read, written in x.
> - any of the above.
> - other..

On a related note, I'd like to point to an (IMHO) interesting paper.

Volatiles Are Miscompiled, and What to Do about It
http://www.cs.utah.edu/~regehr/papers/emsoft08-preprint.pdf

Regards.

Noob, Mar 8, 2011
9. ChadGuest

On Mar 8, 7:18 am, Kenneth Brody <> wrote:
> On 3/7/2011 12:00 PM, Mark Bluemel wrote:
>
>
>
> > On 03/07/2011 04:41 PM, Francois Grieu wrote:
> >> On 07/03/2011 17:33, Mark Bluemel wrote:
> >>> On 03/07/2011 04:05 PM, Francois Grieu
> >>>> Hi, the subject sums it all.

>
> >>>> extern volatile unsigned r;
> >>>> unsigned x,y;

>
> >>>> void test(void)
> >>>> {
> >>>> x=r=y;
> >>>> }

> [...]
> >>> so there is no need for r to be read.

>
> >> I'm unsure of that, and of if "no need" translates to "no read".
> >> My problem boils down to: is the value of (r=y)
> >> - the value read from y (that gets written into r).
> >> - the value read from r (after?) writing the value of y into r.
> >> - any of the above.
> >> - other..

>
> >http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
> > 6.5.16 paragraph 3
> > .... An assignment expression has the value of the left operand after the
> > assignment ....

>
> > I see no mention of other operations after the assignment.

>
> Consider the fact that, with a volatile, the "value of the left operand
> after the assignment" might not necessarily be the value that was just
> assigned to it.
>

Would this be because the assignment produces a side effect?

Chad

Chad, Mar 8, 2011
10. ChadGuest

On Mar 7, 8:33 am, Mark Bluemel <> wrote:
> On 03/07/2011 04:05 PM, Francois Grieu wrote:
>
> > Hi, the subject sums it all.

>
> > extern volatile unsigned r;
> > unsigned x,y;

>
> > void test(void)
> >   {
> >   x=r=y;
> >   }

>
> > What happens:
> > - y is read, written in r and in x.
> > - y is read, written in r; then r is read, written in x.
> > - any of the above.
> > - other..

>
> My reading of this is that your statement is exactly equivalent
> to "x=(r=y);".
>
> That is to say that the value of the expression "r=y" is assigned to x -
> so there is no need for r to be read.

I don't know about C, but some other programming languages would refer
to this as "right associative".

Chad, Mar 8, 2011
11. Guest

Jens <> wrote:
>
> Exactly. The draft of C1X even has a footnote (in assignment
> operators) to make the situation in question explicit:
>
> C1X> The implementation is permitted to read the object to determine
> the value but is not
> C1X> required to, even when the object has volatile-qualified type.

Gee, what a coincidence!
--
Larry Jones

Another casualty of applied metaphysics. -- Hobbes

, Mar 8, 2011
12. Francois GrieuGuest

On 08/03/2011 17:23, Chad wrote:
> On Mar 8, 7:18 am, Kenneth Brody <> wrote:
>> On 3/7/2011 12:00 PM, Mark Bluemel wrote:
>>
>>
>>
>>> On 03/07/2011 04:41 PM, Francois Grieu wrote:
>>>> On 07/03/2011 17:33, Mark Bluemel wrote:
>>>>> On 03/07/2011 04:05 PM, Francois Grieu
>>>>>> Hi, the subject sums it all.

>>
>>>>>> extern volatile unsigned r;
>>>>>> unsigned x,y;

>>
>>>>>> void test(void)
>>>>>> {
>>>>>> x=r=y;
>>>>>> }

>> [...]
>>>>> so there is no need for r to be read.

>>
>>>> I'm unsure of that, and of if "no need" translates to "no read".
>>>> My problem boils down to: is the value of (r=y)
>>>> - the value read from y (that gets written into r).
>>>> - the value read from r (after?) writing the value of y into r.
>>>> - any of the above.
>>>> - other..

>>
>>> http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
>>> 6.5.16 paragraph 3
>>> .... An assignment expression has the value of the left operand after the
>>> assignment ....

>>
>>> I see no mention of other operations after the assignment.

>>
>> Consider the fact that, with a volatile, the "value of the left operand
>> after the assignment" might not necessarily be the value that was just
>> assigned to it.
>>

>
> Would this be because the assignment produces a side effect?

A common example is a register r where some (or all) bits are always
read as 0, regardless of what's written to.

Francois Grieu

Francois Grieu, Mar 8, 2011
13. ChadGuest

On Mar 8, 9:00 am, Francois Grieu <> wrote:
> On 08/03/2011 17:23, Chad wrote:
>
>
>
> > On Mar 8, 7:18 am, Kenneth Brody <> wrote:
> >> On 3/7/2011 12:00 PM, Mark Bluemel wrote:

>
> >>> On 03/07/2011 04:41 PM, Francois Grieu wrote:
> >>>> On 07/03/2011 17:33, Mark Bluemel wrote:
> >>>>> On 03/07/2011 04:05 PM, Francois Grieu
> >>>>>> Hi, the subject sums it all.

>
> >>>>>> extern volatile unsigned r;
> >>>>>> unsigned x,y;

>
> >>>>>> void test(void)
> >>>>>> {
> >>>>>> x=r=y;
> >>>>>> }
> >> [...]
> >>>>> so there is no need for r to be read.

>
> >>>> I'm unsure of that, and of if "no need" translates to "no read".
> >>>> My problem boils down to: is the value of (r=y)
> >>>> - the value read from y (that gets written into r).
> >>>> - the value read from r (after?) writing the value of y into r.
> >>>> - any of the above.
> >>>> - other..

>
> >>>http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
> >>> 6.5.16 paragraph 3
> >>> .... An assignment expression has the value of the left operand afterthe
> >>> assignment ....

>
> >>> I see no mention of other operations after the assignment.

>
> >> Consider the fact that, with a volatile, the "value of the left operand
> >> after the assignment" might not necessarily be the value that was just
> >> assigned to it.

>
> > Would this be because the assignment produces a side effect?

>
> A common example is a register r where some (or all) bits are always
> read as 0, regardless of what's written to.
>

I was think of something like the following....

#include <stdio.h>

int main(void)
{
int a = 5;
int b = 9;

int k = a++ + ++b;

printf("The value of k is: %d\n", k);
printf("a = %d and b = %d\n", a, b);
return 0;
}
[cdalten@localhost oakland]\$ gcc -Wall -Wextra -Wshadow side.c -o side
[cdalten@localhost oakland]\$ ./side
The value of k is: 15
a = 6 and b = 10
[cdalten@localhost oakland]\$

This is how I would attempt to explain the example...

In this case, the value of 'b' is incremented by 1. Then this value,
which is now 10, is added the value of 'a' (which is still 5), to
produce a value of 16. The side effect would be the result of applying
the postincrement operator to 'a'. The result of this side effect is
that the value of 'a' is increased by one. Which would happen after
the sequence point?

Or something along those lines. I'm pretty sure the regulars will
correct me.

Chad

Chad, Mar 8, 2011
14. ChadGuest

On Mar 8, 10:03 am, Chad <> wrote:
> On Mar 8, 9:00 am, Francois Grieu <> wrote:
>
>
>
> > On 08/03/2011 17:23, Chad wrote:

>
> > > On Mar 8, 7:18 am, Kenneth Brody <> wrote:
> > >> On 3/7/2011 12:00 PM, Mark Bluemel wrote:

>
> > >>> On 03/07/2011 04:41 PM, Francois Grieu wrote:
> > >>>> On 07/03/2011 17:33, Mark Bluemel wrote:
> > >>>>> On 03/07/2011 04:05 PM, Francois Grieu
> > >>>>>> Hi, the subject sums it all.

>
> > >>>>>> extern volatile unsigned r;
> > >>>>>> unsigned x,y;

>
> > >>>>>> void test(void)
> > >>>>>> {
> > >>>>>> x=r=y;
> > >>>>>> }
> > >> [...]
> > >>>>> so there is no need for r to be read.

>
> > >>>> I'm unsure of that, and of if "no need" translates to "no read".
> > >>>> My problem boils down to: is the value of (r=y)
> > >>>> - the value read from y (that gets written into r).
> > >>>> - the value read from r (after?) writing the value of y into r.
> > >>>> - any of the above.
> > >>>> - other..

>
> > >>>http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
> > >>> 6.5.16 paragraph 3
> > >>> .... An assignment expression has the value of the left operand after the
> > >>> assignment ....

>
> > >>> I see no mention of other operations after the assignment.

>
> > >> Consider the fact that, with a volatile, the "value of the left operand
> > >> after the assignment" might not necessarily be the value that was just
> > >> assigned to it.

>
> > > Would this be because the assignment produces a side effect?

>
> > A common example is a register r where some (or all) bits are always
> > read as 0, regardless of what's written to.

>
> I was think of something like the following....
>
> #include <stdio.h>
>
> int main(void)
> {
>   int a = 5;
>   int b = 9;
>
>   int k = a++ + ++b;
>
>   printf("The value of k is: %d\n", k);
>   printf("a = %d and b = %d\n", a, b);
>   return 0;}
>
> [cdalten@localhost oakland]\$ gcc -Wall -Wextra -Wshadow side.c -o side
> [cdalten@localhost oakland]\$ ./side
> The value of k is: 15
> a = 6 and b = 10
> [cdalten@localhost oakland]\$
>
> This is how I would attempt to explain the example...
>
> In this case, the value of 'b' is incremented by 1. Then this value,
> which is now 10, is added the value of 'a' (which is still 5), to
> produce a value of 16. The side effect would be the result of applying
> the postincrement operator to 'a'. The result of this side effect is
> that the value of 'a' is increased by one. Which would happen after
> the sequence point?
>
> Or something along those lines. I'm pretty sure the regulars will
> correct me.
>

The part I'm kind of fuzzy about is the ++b

in

int k = a++ + ++b;

The result of the preincrement operator to (applied) b is also a side
effect. However, I think this side effect is applied before the
statement completes. Ie, both b in incremented by one and the side
effect is applied to b. Whereas side effect of a++ is applied *after*
the statement completes.

Chad

Chad, Mar 8, 2011
15. Keith ThompsonGuest

Chad <> writes:
[...]
> The part I'm kind of fuzzy about is the ++b
>
> in
>
> int k = a++ + ++b;
>
> The result of the preincrement operator to (applied) b is also a side
> effect. However, I think this side effect is applied before the
> statement completes. Ie, both b in incremented by one and the side
> effect is applied to b. Whereas side effect of a++ is applied *after*
> the statement completes.

The standard defines the behavior of ++b:

The value of the operand of the prefix ++ operator is
incremented. The result is the new value of the operand
after incrementation. The expression ++E is equivalent to
(E+=1). See the discussions of additive operators and compound
assignment for information on constraints, types, side effects,
and conversions and the effects of operations on pointers.

For both a++ and ++b, the side effect occurs some time between the
preceding and following sequence points.

--
Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Keith Thompson, Mar 8, 2011
16. Spiros BousbourasGuest

On Tue, 8 Mar 2011 08:23:01 -0800 (PST)
Chad <> wrote:
> On Mar 8, 7:18 am, Kenneth Brody <> wrote:
> > Consider the fact that, with a volatile, the "value of the left operand
> > after the assignment" might not necessarily be the value that was just
> > assigned to it.

>
> Would this be because the assignment produces a side effect?

No , it would be because with a volatile , an outside agent outside
the control of the C programme can modify the value of the variable.
With non volatiles this is not allowed to happen.

Spiros Bousbouras, Mar 8, 2011
17. Keith ThompsonGuest

Re: pre/post-increment and sequence points (was Re: x=r=y; // With r volatile. Is r read?)

Kenneth Brody <> writes:
[...]
> Despite the fact that we are using the value of "a++" after the increment,
> and "++b" before the increment, the result is indistinguishable from the
> other way around. (However, there may be a problem with this implementation
> for values of a==INT_MAX and b<0 due to the overflow in "a++". I leave that
> discussion to those who are more versed in the intricacies of the Standard
> than I am.)

If a==INT_MAX, then the behavior of "a++" is undefined, which makes
the behavior of the entire statement undefined. To put it another
way, the compiler is free to generate code based on the assumption
that it *won't* overflow.

--
Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Keith Thompson, Mar 8, 2011
18. Spiros BousbourasGuest

Re: pre/post-increment and sequence points (was Re: x=r=y; // With r

On Tue, 08 Mar 2011 14:58:41 -0500
Kenneth Brody <> wrote:
> On 3/8/2011 1:09 PM, Chad wrote:
> [...]
> > The part I'm kind of fuzzy about is the ++b
> >
> > in
> >
> > int k = a++ + ++b;
> >
> > The result of the preincrement operator to (applied) b is also a side
> > effect. However, I think this side effect is applied before the
> > statement completes. Ie, both b in incremented by one and the side
> > effect is applied to b. Whereas side effect of a++ is applied *after*
> > the statement completes.

>
> No. Both the increments of a and of b are guaranteed to take place before
> the statement completes. (Or, more technically, before the next "sequence
> point".) When, exactly, during the execution of the statement, the
> increments take place is not specified by the Standard.
>
> However, the meaning of "a++" is "the value of a before the increment", and
> "++b" is "the value of b after the increment". However, that does not
> necessarily mean that "b" actually has been incremented by the time the
> value of "++b" is used, nor that "a" won't be incremented before the value
> is read.
>
> In other words, this pseudo-code is a perfectly valid implementation of the
> above code:
>
> ; extern int a,b;
> ; int k = a++ + ++b;
>
> load k,a
> add k,b
> incr k
> incr a
> incr b
>
> In fact, I believe this implementation is just as valid:
>
> incr a
> load k,a
> add k,b
> incr b
>
> Despite the fact that we are using the value of "a++" after the increment,
> and "++b" before the increment, the result is indistinguishable from the
> other way around. (However, there may be a problem with this implementation
> for values of a==INT_MAX and b<0 due to the overflow in "a++".

If a==INT_MAX then a++ produces undefined behavior so all
implementations are valid.

Spiros Bousbouras, Mar 8, 2011
19. Guest

Kenneth Brody <> wrote:
>
> Consider the fact that, with a volatile, the "value of the left operand
> after the assignment" might not necessarily be the value that was just
> assigned to it.
>
> But, apparently that description was ambiguous, and the latest draft of the
> Standard (see elsethread) make it clear that it's implementation defined.

Unspecified, not implementation defined.
--
Larry Jones

These child psychology books we bought were such a waste of money.
-- Calvin's Mom

, Mar 8, 2011
20. Tim RentschGuest

Re: pre/post-increment and sequence points (was Re: x=r=y; // With r volatile. Is r read?)

Keith Thompson <> writes:

> Kenneth Brody <> writes:
> [...]
>> Despite the fact that we are using the value of "a++" after the increment,
>> and "++b" before the increment, the result is indistinguishable from the
>> other way around. (However, there may be a problem with this implementation
>> for values of a==INT_MAX and b<0 due to the overflow in "a++". I leave that
>> discussion to those who are more versed in the intricacies of the Standard
>> than I am.)

>
> If a==INT_MAX, then the behavior of "a++" is undefined, which makes
> the behavior of the entire statement undefined. To put it another
> way, the compiler is free to generate code based on the assumption
> that it *won't* overflow.

The compiler _might_ be free to do that, depending on if and how
the implementation chooses to define the behavior on overflow,
which the implementation is at liberty to do however it wishes.

Tim Rentsch, Mar 11, 2011

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.