Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

volatile in c99

4 views
Skip to first unread message

George

unread,
Nov 30, 2008, 2:54:14 AM11/30/08
to

[after non-response in clc,]
[multi-posted to:]
[comp.std.c]
[comp.arch.embedded]

By trade, I'm a carpenter, and I've been implementing a greener heating
solution for the house I'm flipping including fans that are to be
controlled by an integrated circuit. I expect this solution to help the
house, help the planet, and put more green in my wallet.

It is in the programming for, say, a thermistor, that volatile comes into
play. I thought of doing the whole project in C, which, I thought, was the
best tool for this type of thing. I've now stumbled upon an opinion that
volatile in C99 is not a good thing, and now I have a couple questions.

q1) Is there anybody around with a serious criticism of volatile in C99?

q2) What changed about volatile between C90 and C99?

I have 1256.pdf on my machine now. Thanks for your comment.
--
George

Everywhere that freedom stirs, let tyrants fear.
George W. Bush

Picture of the Day http://apod.nasa.gov/apod/

Rich Webb

unread,
Nov 30, 2008, 6:53:52 AM11/30/08
to
On Sun, 30 Nov 2008 00:54:14 -0700, George <geo...@example.invalid>
wrote:

>
>[after non-response in clc,]
>[multi-posted to:]
>[comp.std.c]
>[comp.arch.embedded]
>
>By trade, I'm a carpenter, and I've been implementing a greener heating
>solution for the house I'm flipping including fans that are to be
>controlled by an integrated circuit. I expect this solution to help the
>house, help the planet, and put more green in my wallet.
>
>It is in the programming for, say, a thermistor, that volatile comes into
>play. I thought of doing the whole project in C, which, I thought, was the
>best tool for this type of thing. I've now stumbled upon an opinion that
>volatile in C99 is not a good thing, and now I have a couple questions.
>
>q1) Is there anybody around with a serious criticism of volatile in C99?
>
>q2) What changed about volatile between C90 and C99?
>
>I have 1256.pdf on my machine now. Thanks for your comment.

AFAIK, the only change was (from the Rationale)

"A new feature of C99: The static storage class specifier and any of
the type-qualifiers, restrict, const or volatile, can appear inside the
[ and ] that are used to declare an array type, but only in the
outermost array type derivation of a function parameter."

which is hardly likely to affect your use of volatile to decorate A/D
registers.

The "restrict" keyword was added, which necessitated some wording
changes in the paragraphs discussing const, volatile, and restrict.

I am not a language lawyer; it will be interesting to read the
discussion.

What prompted the original question/concern?

--
Rich Webb Norfolk, VA

David Brown

unread,
Nov 30, 2008, 7:20:01 AM11/30/08
to
George wrote:
> [after non-response in clc,]
> [multi-posted to:]
> [comp.std.c]
> [comp.arch.embedded]
>

(Don't multi-post - if the post is on-topic and of interest to several
groups, the following discussion is also of interest. Multi-posting
greatly irritates people who follow both groups, and those who haunt
only one of the groups lose out on potentially interesting alternative
viewpoints.)

> By trade, I'm a carpenter, and I've been implementing a greener heating
> solution for the house I'm flipping including fans that are to be
> controlled by an integrated circuit. I expect this solution to help the
> house, help the planet, and put more green in my wallet.
>
> It is in the programming for, say, a thermistor, that volatile comes into
> play. I thought of doing the whole project in C, which, I thought, was the
> best tool for this type of thing. I've now stumbled upon an opinion that
> volatile in C99 is not a good thing, and now I have a couple questions.
>
> q1) Is there anybody around with a serious criticism of volatile in C99?
>
> q2) What changed about volatile between C90 and C99?
>
> I have 1256.pdf on my machine now. Thanks for your comment.

I don't know about specific changes of "volatile" between C90 and C99,
but there is plenty to criticise about "volatile" in C. Much of it is
to do with programmers' misunderstandings and vague specifications in
the standards. I'm sure I'll be corrected if I've misinterpreted the
standards here!

It's too restrictive. You can't specify that a piece of data is
"volatile" for writes but not for reads.

It doesn't correspond directly to what people think - in particular,
people often mistakenly think "volatile" access implies atomic access.

It depends on sequence points, and everything between sequence points is
only loosely specified. Consider this code:

extern volatile int va, vb;
int foo(void) { return (va + vb + va); }

There is no requirement in the standard that says va must be read twice,
or the order in which va and vb are read. The standard only says that
access to volatile data must match up exactly to the expectations of the
abstract machine at the sequence points. So between sequence points the
compiler can read volatile data as often as it wants (either more often
or less often than the source code implies), and it can write volatile
data as often as it wants (as long as the final write is correct).

The compiler is free to remove code that accesses volatile data if it
knows the code is unnecessary. In particular, if your source code reads
volatile data but does not use the result, the compiler may eliminate
the read.

Volatile access ordering only applies to volatiles - people often think
that volatile accesses force the compiler to separate all code before
and after the access. This is simply not true - volatile accesses at
different sequence points must be ordered according to the source code,
but other accesses and code can be reordered by the compiler. For example:

extern volatile int testPin;
static void doSomething(void) { ... }
static void timeSomething(void) {
testPin = 1;
doSomething();
testPin = 0;
}

If the compiler knows that doSomething() does not have any volatile
accesses, it is free to move the entire call before "testPin = 1" or
after "testPin = 0".


Most people believe "volatile" means that the compiler should read or
write the data exactly as specified in the source code, in the same
order and with the same number of reads and writes. As far as I know,
compilers normally implement "volatile" in exactly this way. But the
standards give no guarantees.

Tim Wescott

unread,
Nov 30, 2008, 1:38:09 PM11/30/08
to

My understanding is that "volatile" just tells the compiler not to
optimize out reads; the rest will be done as obscurely (or directly) a
the optimizer is written.

So it is certainly the correct paradigm to use for reading an ADC.
Usually I will declare something like this volatile, read it _once_ at
each loop iteration, and get on with life.

--
Tim Wescott
Control systems and communications consulting
http://www.wescottdesign.com

Need to learn how to apply control theory in your embedded system?
"Applied Control Theory for Embedded Systems" by Tim Wescott
Elsevier/Newnes, http://www.wescottdesign.com/actfes/actfes.html

John Devereux

unread,
Nov 30, 2008, 2:27:43 PM11/30/08
to
David Brown <da...@westcontrol.removethisbit.com> writes:

> The compiler is free to remove code that accesses volatile data if it
> knows the code is unnecessary. In particular, if your source code
> reads volatile data but does not use the result, the compiler may
> eliminate the read.

I did not know that... is it really true? It would seem to make
reliable hardware access impossible. Since "Using the results" could
usually be optimised out by a sufficiently "clever" compiler.


--

John Devereux

Michael R. Kesti

unread,
Nov 30, 2008, 3:26:35 PM11/30/08
to
John Devereux wrote:

Yes, it really is true and it is the reason for the volatile modifier.

--
========================================================================
Michael Kesti | "And like, one and one don't make
| two, one and one make one."
mrkesti at hotmail dot com | - The Who, Bargain

John Devereux

unread,
Nov 30, 2008, 4:22:26 PM11/30/08
to
"Michael R. Kesti" <michae...@comcast.net> writes:

> John Devereux wrote:
>
>>David Brown <da...@westcontrol.removethisbit.com> writes:
>>
>>> The compiler is free to remove code that accesses volatile data if it
>>> knows the code is unnecessary. In particular, if your source code
>>> reads volatile data but does not use the result, the compiler may
>>> eliminate the read.
>>
>>I did not know that... is it really true? It would seem to make
>>reliable hardware access impossible. Since "Using the results" could
>>usually be optimised out by a sufficiently "clever" compiler.
>
> Yes, it really is true and it is the reason for the volatile modifier.

No, David seems to be saying that even *with* the modifier, the
compiler is still free to remove read accesses if the result is not
used. This is contrary to what I have been assuming.


--

John Devereux

Jujitsu Lizard

unread,
Nov 30, 2008, 6:04:46 PM11/30/08
to
"John Devereux" <jo...@devereux.me.uk> wrote in message
news:873ah8n...@cordelia.devereux.me.uk...

I don't believe that David is correct. From a C standard:

[#2] Accessing a volatile object, modifying an object,
modifying a file, or calling a function that does any of
those operations are all side effects,10) which are changes
in the state of the execution environment. Evaluation of an
expression may produce side effects. At certain specified
points in the execution sequence called sequence points, all
side effects of previous evaluations shall be complete and
no side effects of subsequent evaluations shall have taken
place. (A summary of the sequence points is given in annex
C.)

The code:

volatile int x;

...

if (x) ;

or even:

x;

should generate a read access to x. Reason: side-effect.

The Lizard.

CBFalconer

unread,
Nov 30, 2008, 7:06:17 PM11/30/08
to
George wrote:
>
> [after non-response in clc,]
> [multi-posted to:]
> [comp.std.c]
> [comp.arch.embedded]

If you didn't get a response in c.l.c there is probably a reason,
because that is the proper place for this enquiry. In addition,
you have committed the sin of multi-posting. Don't do that.
Instead, you could cross-post, and set follow-ups to your main
newsgroup of interest. This will avoid annoying people in multiple
newsgroups, and ensure that you see all replies in the one place.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.

Michael R. Kesti

unread,
Dec 1, 2008, 12:52:37 AM12/1/08
to
John Devereux wrote:

Oops. Yes, I agree your observation, John, and see that I failed to
accurately interpret his statements.

> This is contrary to what I have been assuming.

It is contrary to how every C compiler I have used, too. The point of
the volatile modifier is to prevent optimizers from removing code such
as David describes.

Walter Banks

unread,
Dec 1, 2008, 4:24:41 AM12/1/08
to

Tim Wescott wrote:

> On Sun, 30 Nov 2008 13:20:01 +0100, David Brown wrote:
>
> > It depends on sequence points, and everything between sequence points is
> > only loosely specified. Consider this code:
> >
> > extern volatile int va, vb;
> > int foo(void) { return (va + vb + va); }
> >
> > There is no requirement in the standard that says va must be read twice,
> > or the order in which va and vb are read. The standard only says that
> > access to volatile data must match up exactly to the expectations of the
> > abstract machine at the sequence points. So between sequence points the
> > compiler can read volatile data as often as it wants (either more often
> > or less often than the source code implies), and it can write volatile
> > data as often as it wants (as long as the final write is correct).
> >
> > The compiler is free to remove code that accesses volatile data if it
> > knows the code is unnecessary. In particular, if your source code reads
> > volatile data but does not use the result, the compiler may eliminate
> > the read.

I am not sure that is completely true, I don't think it is the standards
intent.
For quite a while we have been looking at developers intent in generating
code. It this were true then
va;
could be eliminated in most if not all cases. We have taken the opinion
that the developer had a specific reason for including the statement
and we should retain it in the generated code.

> > Volatile access ordering only applies to volatiles - people often think
> > that volatile accesses force the compiler to separate all code before
> > and after the access. This is simply not true - volatile accesses at
> > different sequence points must be ordered according to the source code,
> > but other accesses and code can be reordered by the compiler. For
> > example:
> >
> > extern volatile int testPin;
> > static void doSomething(void) { ... } static void timeSomething
> (void) {
> > testPin = 1;
> > doSomething();
> > testPin = 0;
> > }
> >
> > If the compiler knows that doSomething() does not have any volatile
> > accesses, it is free to move the entire call before "testPin = 1" or
> > after "testPin = 0".
> >
> >
> > Most people believe "volatile" means that the compiler should read or
> > write the data exactly as specified in the source code, in the same
> > order and with the same number of reads and writes. As far as I know,
> > compilers normally implement "volatile" in exactly this way. But the
> > standards give no guarantees.
>
> My understanding is that "volatile" just tells the compiler not to
> optimize out reads; the rest will be done as obscurely (or directly) a
> the optimizer is written.

In the data flow analysis of our compilers we mark volatile variables
as with having an unknown value which forces at least a single read
to occur between sequence points. Between sequence points we
allow full optimization. This is consistent with both David and Tim's
comments.

Regards

--
Walter Banks
Byte Craft Limited
http://www.bytecraft.com


David Brown

unread,
Dec 1, 2008, 4:23:09 AM12/1/08
to

Looking closer at it, I think you are basically right - "accessing" a
volatile is considered a side-effect. I still do not think there are
guarantees about accesses between sequence points (there is nothing to
say whether two reads are two side-effects, or whether they can be
combined - nor is any ordering implied). But it looks like a request to
read volatile data must cause a real read even if the result is then
ignored.

However, there is (AFAIK) no precise definition of "access". In
particular, if you have a 16-bit volatile item on an 8-bit cpu, it is
not clear when a volatile read forces a read of the whole 16 bits (two
8-bit accesses) and when the compiler can use a single 8-bit read. For
example, will "if (x & 0x0001) ..." just read the low byte? The
standard does say that compilers should perform according underlying
hardware restrictions (for example, on the AVR access to the 16-bit
timer registers must be done in a specific order).

See also:
<http://gcc.gnu.org/onlinedocs/gcc-4.3.2/gcc/Qualifiers-implementation.html>

And regarding C++ (which is not C99, of course, but still interesting):
<http://gcc.gnu.org/onlinedocs/gcc-4.3.2/gcc/Volatiles.html>


In my experience, compilers have always generated volatile reads and
writes based directly on the source code, as people expect them to.
Just because the standards are not as clear as they should be, doesn't
mean compilers don't do a good job!

David Brown

unread,
Dec 1, 2008, 4:25:02 AM12/1/08
to
Michael R. Kesti wrote:
> John Devereux wrote:
>
>> "Michael R. Kesti" <michae...@comcast.net> writes:
>>
>>> John Devereux wrote:
>>>
>>>> David Brown <da...@westcontrol.removethisbit.com> writes:
>>>>
>>>>> The compiler is free to remove code that accesses volatile data if it
>>>>> knows the code is unnecessary. In particular, if your source code
>>>>> reads volatile data but does not use the result, the compiler may
>>>>> eliminate the read.
>>>> I did not know that... is it really true? It would seem to make
>>>> reliable hardware access impossible. Since "Using the results" could
>>>> usually be optimised out by a sufficiently "clever" compiler.
>>> Yes, it really is true and it is the reason for the volatile modifier.
>> No, David seems to be saying that even *with* the modifier, the
>> compiler is still free to remove read accesses if the result is not
>> used.
>
> Oops. Yes, I agree your observation, John, and see that I failed to
> accurately interpret his statements.
>
>> This is contrary to what I have been assuming.
>
> It is contrary to how every C compiler I have used, too. The point of
> the volatile modifier is to prevent optimizers from removing code such
> as David describes.
>

That is certainly how compilers view "volatile". My point was about
what the standards say, which is not nearly as well specified as what
compilers actually *do*.

David Brown

unread,
Dec 1, 2008, 4:31:37 AM12/1/08
to
CBFalconer wrote:
> George wrote:
>> [after non-response in clc,]
>> [multi-posted to:]
>> [comp.std.c]
>> [comp.arch.embedded]
>
> If you didn't get a response in c.l.c there is probably a reason,
> because that is the proper place for this enquiry. In addition,
> you have committed the sin of multi-posting. Don't do that.
> Instead, you could cross-post, and set follow-ups to your main
> newsgroup of interest. This will avoid annoying people in multiple
> newsgroups, and ensure that you see all replies in the one place.
>

And you've committed the sin of posting without first reading other
replies in this thread - I've already commented on multi-posting.

You also seem to misunderstand the concept of "follow-ups". This is
Usenet, not a private help line for any given poster. If a thread is
started as cross-posting to several groups, it should continue as
cross-posting - if it were not of interest to all the groups, it should
not have been posted to them in the first place. Setting a follow-up on
the basis of one's personal group preferences is selfish - threads are
here for the benefit and interest of everyone. Follow-ups are only
appropriate for branches that are clearly relevant in only one group.

Jujitsu Lizard

unread,
Dec 1, 2008, 10:18:30 AM12/1/08
to

"David Brown" <da...@westcontrol.removethisbit.com> wrote in message
news:4933ad03$0$9728$8404...@news.wineasy.se...

The timer thing is always awkward. I've always unioned it and done
something like:

x.b[0] = TREGH;
x.b[1] = TREGL;

if (x.w > 4922)
etc.

But yeah, leaving the ordering decision to the compiler is generally not
done.

I've never thought about the "skip the MSB" scenario, but one can concoct
scenarios for skip the LSB as well ("if (x & 0xFF00)"). A good compiler
WILL skip the access on a normal variable --- unclear what would be done for
volatiles. Good point.

Some recent microcontrollers have caught my attention because they allow
accesses in either order for the latching logic on 16-bit registers. I'm
not sure that that is a good thing. It may just allow an inexperienced
programmer to get further before his project blows up with intermittent bugs
because he never read the data book closely enough to know that there was
latching logic at all.

George

unread,
Dec 1, 2008, 2:45:00 PM12/1/08
to

Thanks all for responses. It looks like compilers do what you'd expect,
while the C standard doesn't specify all that well what that is.

I'd just gone over the use of volatile with a couple of threads here about
"computer driven fans," so I thought I was all straightened out on it.

One of the things that came out of the fortran enclave in tokyo is that
volatile in C is under-defined. Those who responded missed nothing from
the multi-post in comp.std.c, which drew no response.

I like the monday after Thanksgiving. It's Christmas season.
--
George

The momentum of freedom in our world is unmistakable - and it is not
carried forward by our power alone. We can trust in that greater power Who
guides the unfolding of the years. And in all that is to come, we can know
that His purposes are just and true.

Jujitsu Lizard

unread,
Dec 1, 2008, 4:29:20 PM12/1/08
to
"David Brown" <da...@westcontrol.removethisbit.com> wrote in message
news:4933aeff$0$25199$8404...@news.wineasy.se...

You failed to address the question of what someone should do on a reply if
the OP's choice of groups was dubious.

In other words, you're assuming that the original choice of groups was sane.
It may not have been.

The Lizard

David Brown

unread,
Dec 1, 2008, 4:58:35 PM12/1/08
to

I've assumed that the original poster felt the choice of groups was
sane, and should therefore not set follow-ups. Others replying to that
post might disagree and then set follow-ups - that makes a specific branch.

CBFalconer

unread,
Dec 1, 2008, 5:04:23 PM12/1/08
to

And you fail to understand the purpose of a cross-post. It is to
attract the attention of people who may not be watching the primary
group in the first place. Once attracted, there is no need to
maintain the cross-post, since if they have any brains and so wish
they can simply attend the primary group for the period of the
thread. If they really wish to annoy they can cancel the
follow-up, or part of it. However the cross-post with follow-up
generally prevents foolish posts by idiot trolls whose only
objective is to harm the newsgroup.

David Brown

unread,
Dec 1, 2008, 6:10:31 PM12/1/08
to

Yes, I'm *sure* that people will join other groups just to help out on
other particular threads.

Back here in the real world, there are reasons people choice particular
groups to follow, and don't bother with other groups. I'm not
interested in the vast majority of threads in c.l.c or c.s.c - but I
*am* interested in threads that are relevant to both c.a.e. and one of
these groups. I am also interested in what people from these different
groups have to say to each other within a relevant thread. But neither
I nor 99% of the other Usenet regulars are going to join a different
group for a one-off thread - without the cross-group participation, it
would not be nearly as interesting. For example, a C standards
discussion on "volatile" would be of little interest to me without an
embedded slant and input from embedded developers.


CBFalconer

unread,
Dec 1, 2008, 8:07:13 PM12/1/08
to
David Brown wrote:
> CBFalconer wrote:
>
... snip ...

>
>> And you fail to understand the purpose of a cross-post. It is to
>> attract the attention of people who may not be watching the primary
>> group in the first place. Once attracted, there is no need to
>> maintain the cross-post, since if they have any brains and so wish
>> they can simply attend the primary group for the period of the
>> thread. If they really wish to annoy they can cancel the
>> follow-up, or part of it. However the cross-post with follow-up
>> generally prevents foolish posts by idiot trolls whose only
>> objective is to harm the newsgroup.
>
> Yes, I'm *sure* that people will join other groups just to help out
> on other particular threads.

You seem to misunderstand Usenet. To simply reply, just do it. No
special action is needed. The reply goes where it was told. And
'joining other groups' is trivial - bring up the 'subscribe' page,
search for the group name (only one, staring you in the face), tick
something (depends on reader), done. This is only needed if you
plan to follow the discussion.

This assumes you have a semi-reasonable news-reader.

David Brown

unread,
Dec 2, 2008, 2:54:49 AM12/2/08
to

I think I've explained reasonably well why follow-ups should be set in
later posts on a thread, rather than the first one. If you don't
already agree, it's unlikely that you'll change your mind if I re-state
it. And you are not going to change *my* mind in this case (I
understand exactly what you are saying, and disagree with it). So I
suggest we give it up for now (until the next cross-post...).

CBFalconer

unread,
Dec 2, 2008, 4:30:47 PM12/2/08
to
David Brown wrote:
>
... snip ...

>
> I think I've explained reasonably well why follow-ups should be
> set in later posts on a thread, rather than the first one. If
> you don't already agree, it's unlikely that you'll change your
> mind if I re-state it. And you are not going to change *my*
> mind in this case (I understand exactly what you are saying,
> and disagree with it). So I suggest we give it up for now
> (until the next cross-post...).

Agreed. :-)

0 new messages