What is the difference between a static global and a static volatile variable?

Manoj Doubts picture Manoj Doubts · Dec 6, 2008 · Viewed 96.7k times · Source

I have used a static global variable and a static volatile variable in file scope,

both are updated by an ISR and a main loop and main loop checks the value of the variable.

here during optimization neither the global variable nor the volatile variable are optimized. So instead of using a volatile variable a global variable solves the problem.

So is it good to use global variable instead of volatile?

Any specific reason to use static volatile??

Any example program would be appreciable.

Thanks in advance..

Answer

Brian R. Bondy picture Brian R. Bondy · Dec 6, 2008

First let me mention that a static global variable, is the same as a global variable, except that you are limiting the variable to the scope of the file. I.e. you can't use this global variable in other files via the extern keyword.

So you can reduce your question to global variables vs volatile variables.

Now onto volatile:

Like const, volatile is a type modifier.

The volatile keyword was created to prevent compiler optimizations that may make code incorrect, specifically when there are asynchronous events.

Objects declared as volatile may not be used in certain optimizations.

The system always reads the current true value of a volatile object at the point it is used, even if a previous instruction asked for a value from the same object. Also, the value of the object is written immediately on assignment. That means there is no caching of a volatile variable into a CPU register.

Dr. Jobb's has a great article on volatile.

Here is an example from the Dr. Jobb's article:

class Gadget
{
public:
    void Wait()
    {
        while (!flag_)
        {
            Sleep(1000); // sleeps for 1000 milliseconds
        }
    }
    void Wakeup()
    {
        flag_ = true;
    }
    ...
private:
    bool flag_;
};

If the compiler sees that Sleep() is an external call, it will assume that Sleep() cannot possibly change the variable flag_'s value. So the compiler may store the value of flag_ in a register. And in that case, it will never change. But if another thread calls wakeup, the first thread is still reading from the CPU's register. Wait() will never wake-up.

So why not just never cache variables into registers and avoid the problem completely? It turns out that this optimization can really save you a lot of time overall. So C/C++ allows you to explicitly disable it via the volatile keyword.

The fact above that flag_ was a member variable, and not a global variable (nor static global) does not matter. The explanation after the example gives the correct reasoning even if you're dealing with global variables (and static global variables).

A common misconception is that declaring a variable volatile is sufficient to ensure thread safety. Operations on the variable are still not atomic, even though they are not "cached" in registers

volatile with pointers:

Volatile with pointers, works like const with pointers.

A variable of type volatile int * means that the variable that the pointer points to is volatile.

A variable of type int * volatile means that the pointer itself is volatile.