Can a pointer be volatile?

僤鯓⒐⒋嵵緔 提交于 2021-02-06 07:56:08

问题


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?


回答1:


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.




回答2:


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.




回答3:


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.




回答4:


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.




回答5:


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.




回答6:


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;
}


来源:https://stackoverflow.com/questions/33280881/can-a-pointer-be-volatile

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!