Re: Another ANSI C question about 'volatile'
From: Tim Rentsch (txr_at_alumnus.caltech.edu)
Date: 08/16/04
- Next message: Pieter Claassen: "Re: hash table problems being resolved"
- Previous message: Jarno A Wuolijoki: "Re: Generate a random integer of set [0,3]"
- In reply to: Jack Klein: "Re: Another ANSI C question about 'volatile'"
- Next in thread: Keith Thompson: "Re: Another ANSI C question about 'volatile'"
- Reply: Keith Thompson: "Re: Another ANSI C question about 'volatile'"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: 16 Aug 2004 10:33:06 -0700
Jack Klein <jackklein@spamcop.net> writes:
> On 15 Aug 2004 20:40:44 -0700, Tim Rentsch <txr@alumnus.caltech.edu>
> > [stuff omitted]
> >
> > I'd thought of the 'y = *(volatile int *)&x;' before, but I concluded
> > it had the same problem as 'y = (volatile int)x;' -- because the
> > subexpression '(volatile int *)&x' isn't an lvalue (by which I mean,
> > can't be on the left hand side of an assignment operator), the
> > 'volatile' type qualifier is discarded. Or do I misunderstand
> > what the standard means by 'lvalue'?
>
> Yes, you did understand what is meant by 'lvalue' in this case.
>
> The cast is on the address of x. The result of the cast is indeed an
> lvalue of type 'pointer to volatile int'. The pointer itself is not
> volatile, which would indeed be meaningless. But the type pointed to
> by the pointer is not an lvalue, and that is what the 'volatile' in
> the cast applies to.
Here is my problem. The result of the cast is not an "lvalue" as I am
used to the term. Reason being, writing an assignment statement that
starts
(volatile int *) &x = ...
isn't legal. Of course it is legal if there is a '*' in front of the
cast, but that's a different expression. My best understanding now
is that the expression '(volatile int *) &x' is an 'lvalue' as the
term is used (and defined) within the C standard. If this expression
is an lvalue, then the 'volatile' qualifier is retained, and
everything works fine. And -- as I just found out -- the Rationale
has a supporting statement along these lines:
If it is necessary to access a non-volatile object using
volatile semantics, the technique is to cast the address
of the object to the appropriate pointer-to-qualified type,
then dereference the pointer.
So there you have it.
> > Incidentally, what about this idea:
> >
> > int * volatile xp = &x, y = *xp;
>
> No, this does not do the same thing at all. Type qualifiers 'const'
> and 'volatile' (and probably 'restrict', but I haven't checked) modify
> what appears to their left. In this case you are defining 'xp' as a
> volatile pointer to a non-volatile int.
>
> Technically that should mean that the compiler must read the value of
> the pointer xp every time you dereference it, rather than relying on a
> cached value in a register or whatever. Common sense would indicate
> that a compiler, needing to reread xp each time, would then
> dereference it to access memory each time, but the standard does not
> require this behavior.
>
> You are unlikely to find one, but since the integer pointed to by xp
> is not volatile, a compiler would be within its rights to read the
> value of xp each time, compare it to a cached value, and use a cached
> value for '*xp' if 'xp' itself is still the same as the last time it
> was dereferenced.
Yes, I realized this declaration was declaring the pointer as volatile
rather than what it points to. But you're right, I didn't expect that
a particularly perverse compiler could circumvent that and still be
conformant. A very interesting point - thank you.
> > I don't think of this as a memory barrier issue. I want to capture
> > the value that the global 'x' has at the beginning of the function,
> > and guarantee that exactly that same value is used later in the
> > function. Any changes that happen to 'x', for whatever reason, while
> > the function is running must not be allowed to affect what the
> > function does, which should depend on the value that 'x' has at function
> > start and not any subsequent values.
>
> Any compiler that did not behave the way you describe would be
> horribly broken. Don't worry about it.
>
> > > This is all *way* outside the realm of Standard C, which does not
> > > support multiprocessing at all, and has quite limited support for
> > > interruptions (such as signals) in a single-processing model.
> >
> > Is it? I thought one of the reasons for having 'volatile' is
> > to enable such things as this in operating system code, which
> > is in fact the area of application in this case.
>
> What makes you think that the compiler is trying to optimize away a
> local variable that stores the value of a file-scope object?
Sadly, because it appears that this has happened in similar cases
and that caused difficult-to-discover bugs.
As for the compiler being broken - perhaps it is, but my belief is (if
there is no mention of 'volatile') the standard allows the compiler to
behave in this way and still be conformant.
> In any
> case, if the value of 'x' is subject to change while a function is
> executing, and that function does not write to 'x', write via a
> pointer that might alias to 'x', or call another function that might
> modify 'x', that means that the value of 'x' might change
> asynchronously and beyond the scope of the compiler.
>
> In that case, 'x' should be defined as volatile in the first place.
Oh, no argument there. It wasn't because of "practical considerations."
If you know what I mean.....
thanks again for the help!
- Next message: Pieter Claassen: "Re: hash table problems being resolved"
- Previous message: Jarno A Wuolijoki: "Re: Generate a random integer of set [0,3]"
- In reply to: Jack Klein: "Re: Another ANSI C question about 'volatile'"
- Next in thread: Keith Thompson: "Re: Another ANSI C question about 'volatile'"
- Reply: Keith Thompson: "Re: Another ANSI C question about 'volatile'"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|