I find that on some IDE/compilers, like AVR codevision, that all global variables are treated as volatile.
As a result, each time the compiler manipulates a global variable, it loads it out of memory, performes some operation on or using it, and then, if modified, writes it back to memory. This results in the code producing (usually) needless read-modify-writes, and lots of code bloat and speed cost.
Compared to most compilers, GCC etc, the volatile keyword is required to ensure the compiler makes no assumptions to the value of a variable.
For the newbie -
Without the volatile keyword, there is assumption by the compiler, that a variable is not being modified elsewhere, so when it loads a (global) variable from memory say at the start of a function, that it doesnt need to reload it to ensure it has the update to date version of it.
the compiler has no idea if the variable you reference in some part of the program will be modified somewhere else . And this might happen when an interrupt handler is executed.
If a variable may be modified outside a function , and if it is modified, if the behaviour of the function would be modified as a result ----, for example during an interrupt handler event might modify a counter variable , (while the 'base' function is being executed) , the use of the variable must be guarded by , usually, disabling interrupts around the use of the variable, so it cannot change while you are making decisions based on the value.
The codevision read modify write method doesnt prevent this because an interrupt may be executed between the 'read - modify - write' steps. I must ask Pavel why he does this.
Many use global variables when they need variable state persistence across function calls. The better method is to use static variables in functions. The compiler does not have to guess if it is being used outside the function because it's private (in a C sense).
Golly I have realised that this is quite a subject, not the original two line reply I wanted to make !
When working with hardware, where peripheral registers may change at any time, like say a UART serial buffer bit telling you there is more data, the definitions for a device in the header file will (likely) be using the volatile keyword to tell the compiler ' do not assume anything'.
Volatile requirements around peripheral interaction, and interrupt handlers are always new traps for new embedded programmers.