Take the 2-minute tour ×

Consider the following:

volatile uint32_t i;

How do I know if gcc did or did not treat i as volatile? It would be declared as such because no nearby code is going to modify it, and modification of it is likely due to some interrupt.

I am not the world's worst assembly programmer, but I play one on TV. Can someone help me to understand how it would differ?

If you take the following stupid code:

#include <stdio.h>
#include <inttypes.h>

volatile uint32_t i;

int main(void)
        if (i == 64738)
                return 0;
                return 1;

Compile it to object format and disassemble it via objdump, then do the same after removing 'volatile', there is no difference (according to diff). Is the volatile declaration just too close to where its checked or modified or should I just always use some atomic type when declaring something volatile? Do some optimization flags influence this?

Note, my stupid sample does not fully match my question, I realize this. I'm only trying to find out if gcc did or did not treat the variable as volatile, so I'm studying small dumps to try to find the difference.

share|improve this question
Program has undefined behavior (access of an uninitialized variable), I think. –  MSalters Mar 13 '09 at 13:26
It states in the question: "stupid sample". On the purist side one could add extern. –  Anonymous Mar 13 '09 at 13:38
@MSalters, its not a program, its a snippet that I typed in quickly. I know i is not initialized and a conditional depends on it. –  Tim Post Mar 13 '09 at 13:38
@unknown, I think you mean s/extern/static ? 'i' is defined in that module. –  Tim Post Mar 13 '09 at 13:40
"there is no difference" could mean one of two things: (a) a compiler bug completely ignores "volatile" -- that would be bad. Or (b) the compiler carefully respects volatile, skipping any optimizations that would break it. Then when you compiled it without volatile, the compiler happened to use exactly the same set of optimizations, skipping (although it wasn't required to) optimizations that would break volatile. This is perfectly fine -- we expect this to happen when we compile without optimization. –  David Cary Mar 14 '11 at 20:03

7 Answers 7

up vote 11 down vote accepted

Many compilers in some situations don't treat volatile the way they should. See this paper if you deal much with volatiles to avoid nasty surprises: Volatiles are Miscompiled, and What to Do about It. It also contains the pretty good description of the volatile backed with the quotations from the standard.

To be 100% sure, and for such a simple example check out the assembly output.

share|improve this answer
The assembly output with or without the volatile keyword is the same on this simple sample, which makes me wonder if gcc just obeys the declaration or decides if the variable is not going to be modified. So, how can I tell from the assembly output? –  Tim Post Mar 13 '09 at 13:21
Try throwing in some optimisation flags, small difference should appear. –  Anonymous Mar 13 '09 at 13:33
THANKS! :) I have to obey the CFLAGS that a user sets when compiling, so I'm pulling my hair out to find out of something volatile was treated as ordinary. –  Tim Post Mar 13 '09 at 13:43

Try setting the variable outside a loop and reading it inside the loop. In a non-volatile case, the compiler might (or might not) shove it into a register or make it a compile time constant or something before the loop, since it "knows" it's not going to change, whereas if it's volatile it will read it from the variable space every time through the loop.

Basically, when you declare something as volatile, you're telling the compiler not to make certain optimizations. If it decided not to make those optimizations, you don't know that it didn't do them because it was declared volatile, or just that it decided it needed those registers for something else, or it didn't notice that it could turn it into a compile time constant.

share|improve this answer

As far as I know, volatile helps the optimizer. For example, if your code looked like this:

int foo() {
    int x = 0;
    while (x);
    return 42;

The "while" loop would be optimized out of the binary.

But if you define 'x' as being volatile (ie, volatile int x;), then the compiler will leave the loop alone.

share|improve this answer

Your little sample is inadequate to show anything. The difference between a volatile variable and one that isn't is that each load or store in the code has to generate precisely one load or store in the executable for a volatile variable, whereas the compiler is free to optimize away loads or stores of non-volatile variables. If you're getting one load of i in your sample, that's what I'd expect for volatile and non-volatile.

To show a difference, you're going to have to have redundant loads and/or stores. Try something like

int i = 5;
int j = i + 2;
i = 5;
i = 5;

changing i between non-volatile and volatile. You may have to enable some level of optimization to see the difference.

The code there has three stores and two loads of i, which can be optimized away to one store and probably one load if i is not volatile. If i is declared volatile, all stores and loads should show up in the object code in order, no matter what the optimization. If they don't, you've got a compiler bug.

share|improve this answer

It should always treat it as volatile.

The reason the code is the same is that volatile just instructs the compiler to load the variable from memory each time it accesses it. Even with optimization on, the compiler still needs to load i from memory once in the code you've written, because it can't infer the value of i at compile time. If you access it repeatedly, you'll see a difference.

share|improve this answer
It should, but compilers are allowed to ignore the hint. I don't think GCC ignores the hint, but they are allowed to. –  Max Lybbert Mar 13 '09 at 23:29
For the record, Hans Boehm wrote a very useful document about volatile and it's non-usability on modern hardware at open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2016.html . –  Max Lybbert Jun 17 '11 at 22:57
@MaxLybbert "It should, but compilers are allowed to ignore the hint." Nonsense. Of course, they aren't allowed to ignore volatile. –  curiousguy Oct 26 '11 at 19:31
@curiousguy I've learned a bit in two years. The Boehm document I linked to has some useful information, as does cs.utah.edu/~regehr/papers/emsoft08-preprint.pdf . The big thing to note is that volatile almost definitely doesn't mean what the programmer thinks (see the Boehm link). Even when the compiler "does the right thing," modern CPUs still manage muck things up (or, as Boehm puts it, "most implementations do not insert sufficient memory fences to guarantee that other threads, or even hardware devices, see volatile operations in the order in which they were issued"). –  Max Lybbert Oct 28 '11 at 0:36

Any modern compiler has multiple stages. One of the fairly easy yet interesting questions is whether the declaration of the variable itself was parsed correctly. This is easy because the C++ name mangling should differ depending on the volatile-ness. Hence, if you compile twice, once with volatile defined away, the symbol tables should differ slightly.

share|improve this answer
Which compiler has name mangling for variables? –  curiousguy Oct 26 '11 at 19:30
AFAICT, all, since there can be many variables sharing the same name. They'd have to be in different scopes, so name mangling must include at least that scope. –  MSalters Oct 27 '11 at 9:12

Read the standard before you misquote or downvote. Here's a quote from n2798: The cv-qualifiers

7 Note: volatile is a hint to the implementation to avoid aggressive optimization involving the object because the value of the object might be changed by means undetectable by an implementation. See 1.9 for detailed semantics. In general, the semantics of volatile are intended to be the same in C++ as they are in C.

The keyword volatile acts as a hint. Much like the register keyword. However, volatile asks the compiler to keep all its optimizations at bay. This way, it won't keep a copy of the variable in a register or a cache (to optimize speed of access) but rather fetch it from the memory everytime you request for it.

Since there is so much of confusion: some more. The C99 standard does in fact say that a volatile qualified object must be looked up every time it is read and so on as others have noted. But, there is also another section that says that what constitutes a volatile access is implementation defined. So, a compiler, which knows the hardware inside out, will know, for example, when you have an automatic volatile qualified variable and whose address is never taken, that it will not be put in a sensitive region of memory and will almost certainly ignore the hint and optimize it away.

This keyword finds usage in setjmp and longjmp type of error handling. The only thing you have to bear in mind is that: You supply the volatile keyword when you think the variable may change. That is, you could take an ordinary object and manage with a few casts.

Another thing to keep in mind is the definition of what constitutes a volatile access is left by standard to the implementation.

If you really wanted different assembly compile with optimization

share|improve this answer
Definitely not a hint. See C and C++ standards on "observable behavior". "float" is a hint in comparison to volatile. –  MSalters Mar 13 '09 at 13:09
Exactly. Read the whole thing -- the standard defines what constitutes a volatile access to the implementation. –  dirkgently Mar 13 '09 at 13:20
@MSalters: Updated with quote. –  dirkgently Mar 13 '09 at 13:25
Yes, compilers are free to ignore the hint. –  Max Lybbert Mar 13 '09 at 23:30
Then why does the standard say "volatile is a hint" and not "volatile is a command"? –  Max Lybbert Mar 15 '09 at 7:14

Your Answer


