tags:

views:

365

answers:

2

Consider the following code:

int main()                                                                      
{                                                                             
    int i;                                                                      
    volatile int* p = &i;                                                       
    int *v = p;                                                                 
    return 0;                                                                   
}

This gives an error in g++:

$ g++ -o volatile volatile.cpp 
volatile.cpp: In function ‘int main()’:
volatile.cpp:6: error: invalid conversion from ‘volatile int*’ to ‘int*’

My intention was that I want to make p volatile. However, once I've read the value of p, I don't care if accessing v is volatile. Why is it required that v be declared volatile?

This is hypothetical code of course. In a real situation you could imagine that p points to a memory location, but is modified externally and I want v to point to the location that p pointed to at the time of v = p, even if later p is externally modified. Therefore p is volatile, but v is not.

By the way I am interested in the behaviour both when this is considered C and C++, but in C this only generates a warning, not an error.

+15  A: 

If you mean that the pointer should be volatile, rather than the object it points to, then declare it as

int* volatile p;
Mike Seymour
This is your answer, Steve. I'd like to add this recommendation: *Always write the const / volatile qualifier **after** what you wanted to qualify.* It is the only way to write qualifiers *consistently*, because you can write both `volatile int` and `int volatile` when you want a volatile integer, but only `int * volatile` will give you a volatile *pointer*.
DevSolar
Thanks!!! I didn't even think of this. Completely logical, thank you.
Steve
The easiest way to read declarations (for both const and volatile placement) is simply to read them backwards. Hence "int * volatile" is a "volatile pointer to an int".
Adisak
+9  A: 

In C++ the volatile keyword applies the same kinds of restriction on what you can do as const does. The Standard refers to this as 'cv-qualification' as in 'const/volatile qualification. Consts can only be used by consts, and in much the same way volatiles can only be used by volatiles.

Just as an aside, this can help you in writing multithreaded code. Not by virtue of employing some compiler magic that makes your variable suddenly atomic or anything like that, but by forcing you to only act on volatile data in a volatile way. See this Alexandrescu article for more info.

John Dibling
Also worth a read: http://www.mikeash.com/pyblog/friday-qa-2009-07-10-type-specifiers-in-c-part-3.html (aka. don't forget about OSMemoryBarrier)
slf