Quite the opposite, actually. The volatile keyword tells the compiler that the variable may change as a result of something invisible to the compiler, and that the compiler needs to care about the changes that occur. If code has multiple reads, and the compiler can see nothing that changes the value, then "volatile" tells the compiler it cannot omit reads.
Originally Posted by cyberfish
To answer the original question though, volatile (like const) is always an attribute of the thing immediately to its left in an expression, unless it is on the left, in which case it refers to the right.
guarantees that *ptr (if it is accessed) will always dereference 0xsomeaddress. It is equivalent to
volatile int *ptr = 0xsomeaddress;
If you care about ptr itself being changed by something invisible to the compiler, then you need to do
int volatile *ptr = 0xsomeaddress;
(noting that the first usage of volatile can be either before or after the int keyword).
volatile int * volatile ptr = 0xsomeaddress;