Explanation of Volatile?

Can someone please provide a better explanation of when to use ""volatile"?

I read the Arduino reference page and understand it's used for values that might change and often used with interrupts, it's pulled from the RAM and not the storage register, but if you code a variable using "int", can't that values also change?

Should you never just code using "int" alone, and always make sure you label a variable "const" or "volatile"? Thanks in advance.

If I write this:

int a = 3;

void loop(){

    if (a == 4){
         //do something
    }

    //  some more stuff that doesn't affect the value of a
}

Then the compiler will simply remove the if statement altogether since a will not ever equal 4. The compiler can see that the case is impossible so it will simply remove the code when it does the compile.

But what I also had an interrupt routine that could change a?

int a = 3;

void setup(){
    attachInterrupt(0, myFunc, CHANGE);
}

void loop(){
    if (a == 4){
         //do something
    }

    //  some more stuff that doesn't affect the value of a
}


void myFunc(){
     a = 4;
}

The compiler would still see this as a case for optimization. It would see that the ISR function isn't called from loop or anywhere that is called from loop. It can't know that myFunc is called from an interrupt. So it still thinks that a will always be 3 and that the if statement can never be true. So it will still cut it out.

But if I make a volatile:

volatile int a = 3;

void setup(){
    attachInterrupt(0, myFunc, CHANGE);
}

void loop(){
    if (a == 4){
         //do something
    }

    //  some more stuff that doesn't affect the value of a
}


void myFunc(){
     a = 4;
}

Now the compiler will see that a is volatile. That lets it know that it can't optimize it away because it may change from somewhere else. So the compiler will not optimize this code away and the if statement still works.

3 Likes

Equally important, volatile also causes the compiler to generate code that always reads the variable from RAM and does not "cache" the last read value in a register. volatile should ALWAYS be used on any variable that can be modified an interrupt, or any external source. For example, chip register addresses (think of, for example, the status register in a UART or other communications chip) should also be declared as volatile, so the compiler will always read the physical register.

Regards,
Ray L.

1 Like

Hello,

The Arduino reference page is not where you should look to learn coding :slight_smile:

http://en.cppreference.com/w/c/language/volatile
http://en.cppreference.com/w/c/language/const

A nice article about it:

What everyone else said. volatile tells the C++ compiler not to be clever about optimising things out.