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

F

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..

TIA,
Francois Grieu
 
M

Mark Bluemel

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.
 
F

Francois Grieu

On 03/07/2011 04:05 PM, Francois Grieu

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
 
M

Mark Bluemel

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.
 
L

lawrence.jones

Francois Grieu said:
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.
 
J

Jens

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
 
F

Francois Grieu

On 07/03/2011 22:42 said:
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
 
C

Chad

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
 
C

Chad

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".
 
L

lawrence.jones

Jens said:
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! :)
 
F

Francois Grieu

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
 
C

Chad

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
 
C

Chad

On 08/03/2011 17:23, Chad 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
 
K

Keith Thompson

Chad said:
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.
 
S

Spiros Bousbouras

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.
 
K

Keith Thompson

Kenneth Brody said:
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.
 
S

Spiros Bousbouras

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.
 
L

lawrence.jones

Kenneth Brody said:
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.
 
T

Tim Rentsch

Keith Thompson said:
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.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top