vishal
vishal

Reputation: 2391

Can a pointer be volatile?

Consider the following code:

int square(volatile int *p)
{
    return *p * *p;
}

Now, the volatile keyword indicates that the value in a memory location can be altered in ways unknown to the compiler or have other unknown side effects (e.g. modification via a signal interrupt, hardware register, or memory mapped I/O) even though nothing in the program code modifies the contents.

So what exactly happens when we declare a pointer as volatile?

Will the above mentioned code always work, or is it any different from this:

int square(volatile int *p)
{
    int a = *p;
    int b = *p
    return a*b;
}

Can we end up multiplying different numbers, as pointers are volatile?

Or is there better way to do so?

Upvotes: 24

Views: 17565

Answers (7)

fn_cats
fn_cats

Reputation: 32

    int square(volatile int *p)
    {
        int a = *p;
        int b = *p
        return a*b;
    }

Since it is possible for the value of *ptr to change unexpectedly, it is possible for a and b to be different. Consequently, this code could return a number that is not a square! The correct way to code this is:

    long square(volatile int *p)
    {
        int a;
        a = *p;
        return a * a;
    }

Upvotes: 0

edmz
edmz

Reputation: 8492

Can a pointer be volatile?

Absolutely; any type, excluding function and references, may be volatile-qualified.

Note that a volatile pointer is declared T *volatile, not volatile T*, which instead declares a pointer-to-volatile.

A volatile pointer means that the pointer value, that is its address and not the value pointed to by, may have side-effects that are not visible to the compiler when it's accessed; therefore, optimizations deriving from the "as-if rule" may not be taken into account for those accesses.


int square(volatile int *p) { return *p * *p; }

The compiler cannot assume that reading *p fetches the same value, so caching its value in a variable is not allowed. As you say, the result may vary and not be the square of *p.

Concrete example: let's say you have two arrays of ints

int a1 [] = { 1, 2, 3, 4, 5 };
int a2 [] = { 5453, -231, -454123, 7565, -11111 };

and a pointer to one of them

int * /*volatile*/ p = a1;

with some operation on the pointed elements

for (int i = 0; i < sizeof(a1)/sizeof(a1[0]); ++i) 
       *(p + i) *= 2;

here p has to be read each iteration if you make it volatile because, perhaps, it may actually point to a2 due to external events.

Upvotes: 16

dspfnder
dspfnder

Reputation: 1123

Yes, a pointer can be volatile if the variable that it points to can change unexpectedly even though how this might happen is not evident from the code.

An example is an object that can be modified by something that is external to the controlling thread and that the compiler should not optimize.

The most likely place to use the volatile specifier is in low-level code that deals directly with the hardware and where unexpected changes might occur.

Upvotes: 1

SingerOfTheFall
SingerOfTheFall

Reputation: 29966

The volatile keyword is a hint for the compiler (7.1.6.1/7):

Note: volatile is a hint to the implementation to avoid aggressive optimization involving the object because the value of the object might be changed by means undetectable by an implementation. Furthermore, for some implementations, volatile might indicate that special hardware instructions are required to access the object. See 1.9 for detailed semantics. In general, the semantics of volatile are intended to be the same in C ++ as they are in C. — end note ]

What does it mean? Well, take a look at this code:

bool condition = false;
while(!condition)
{
    ...
}

by default, the compiler will easilly optimize the condition out (it doesn't change, so there is no need to check it at every iteration). If you, however, declare the condition as volatile, the optimization will not be made.

So of course you can have a volatile pointer, and it is possible to write code that will crash because of it, but the fact that a variable is volative doesn't mean that it is necessarily going to be changed due to some external interference.

Upvotes: 2

Lapshin Dmitry
Lapshin Dmitry

Reputation: 1124

Yes. int * volatile.

In C++, keywords according to type/pointer/reference go after the token, like int * const is constant pointer to integer, int const * is pointer to constant integer, int const * const is constant pointer to constant integer e.t.c. You can write keyword before the type only if it's for the first token: const int x is equal to int const x.

Upvotes: 2

user5473178
user5473178

Reputation:

You may be end up multiplying different numbers because it's volatile and could be changed unexpectedly. So, you can try something like this:

int square(volatile int *p)
{
int a = *p;
return a*a;
}

Upvotes: 0

Damon
Damon

Reputation: 70186

Yes, you can of course have a volatile pointer.

Volatile means none more and none less than that every access on the volatile object (of whatever type) is treated as a visible side-effect, and is therefore exempted from optimization (in particular, this means that accesses may not be reordered or collapsed or optimized out alltogether). That's true for reading or writing a value, for calling member functions, and of course for dereferencing, too.

Note that when the previous paragraph says "reordering", a single thread of execution is assumed. Volatile is no substitute for atomic operations or mutexes/locks.

In more simple words, volatile generally translates to roughly "Don't optimize, just do exactly as I say".

In the context of a pointer, refer to the exemplary usage pattern given by Chris Lattner's well-known "What every programmer needs to know about Undefined Behavior" article (yes, that article is about C, not C++, but the same applies):

If you're using an LLVM-based compiler, you can dereference a "volatile" null pointer to get a crash if that's what you're looking for, since volatile loads and stores are generally not touched by the optimizer.

Upvotes: 12

Related Questions