4

I understand when you need a pointer to a volatile value (e.g. doing a read of a memory mapped peripheral). But when would you need the pointer itself to be volatile?>

Natan Streppel
  • 5,759
  • 6
  • 35
  • 43
fred basset
  • 9,774
  • 28
  • 88
  • 138
  • 1
    Same reason, the contents (i.e. the address) might change outside of the current source code. C can be used on all kinds of devices where this might happen. – Crowman May 03 '14 at 20:51
  • 1
    Can you elaborate ok what you mean "by the pointer itself to be volatile"? Remember, `volatile char *p` declares `p` to be a pointer to a `volatile char`. Are you asking about something like: `char *volatile p;` which declares `p` to be a `volatile` pointer to `char`? If so, it's for the same reason(s) that any variable might be made `volatile`. – Nik Bougalis May 03 '14 at 20:51
  • unsigned char* volatile ptr; // pointer itself is volatile – fred basset May 03 '14 at 20:52
  • Paul, what's a concrete example of where this could happen? My context is embedded systems. – fred basset May 03 '14 at 20:53
  • Right, it is. And the answer remains: for the same reason why any other variable might be declared `volatile`. Imagine, for example, some hardware that stores a pointer to a function at some known, fixed location in memory and updates it every 74 milliseconds. – Nik Bougalis May 03 '14 at 20:55
  • @fredbasset: Right, something like Nik says. I don't have any concrete examples, but you might have a pointer to a function or a data structure that the hardware might make point to something else if you change a setting via a button, for instance. – Crowman May 03 '14 at 20:56
  • OK I see. So for example an ISR could change a function pointer? – fred basset May 03 '14 at 20:57
  • Can we convert the comments to a decent answer and upvote it? – this May 03 '14 at 21:23
  • Yes pls. add an answer and I'll mark it as correct. – fred basset May 03 '14 at 21:31

1 Answers1

4

To elaborate on my comment a little bit, it's important to first keep in mind what volatile means: it's a signal to the compiler that the variable being declared can change in unexpected ways through mechanisms that the compiler cannot see or control and that reads and writes may have side-effects. As a result, a compiler will typically reload the value of the variable every time from main memory instead of using a cached value and will not perform optimizations that remove, reorder or elide reads or writes to such volatile variables.

Typically this sort of thing is something that most userspace code doesn't have to worry about and legitimate uses of volatile from there are few and far between.

Your question also references a subtle and not well-known feature of the language: the ability to declare a pointer itself as volatile (or const) instead of thing that it points to. You do this with this syntax:

int *volatile p = 0x74;

This declares a volatile pointer that points to an int at memory location 0x74. Contrast this with:

volatile int *p = 0x74;

which declares a pointer to a volatile int at address 0x74

The difference between this two is what happens when you access p. We'll only concern ourselves with the read case:

In the case of the pointer to volatile int for every read access the compiler will go to memory location 0x74 and read (perhaps using special CPU instructions) the int value at that location - the value will not be cached by the code (but it might be by the hardware).

In the case of the volatile pointer to int the compiler will reload the value of the pointer at every access and then go and read the int at that address. The address will not be cached in the code (but again, it may be cached by the hardware).

And similarly with writes.

Again, be sure to remember that volatile restricts the compiler (e.g. it can't optimize away a write or a read) since any operation on the volatile variable might have side-effects that are not visible to the compiler. An example of such a side effect might be generating an interrupt, blinking an LED, writing an audit record or changing the value of a register.

Nik Bougalis
  • 10,495
  • 1
  • 21
  • 37
  • There's more to `volatile` than the compiler caching accesses. See [this example](http://pastebin.com/EARgAKqa): without `volatile`, with a sufficiently high level of optimizations, the compiler could remove the first write since it'll be overwritten immediately. This could have catastrophic implications if `foo_register` pointed to a memory-mapped register that expected a certain sequence of writes. (Depending on the hardware, you may also need barriers to stop reordering.) – zneak May 03 '14 at 21:31
  • Right, I wasn't done writing and hit "post" prematurely. – Nik Bougalis May 03 '14 at 21:34
  • `volatile` doesn't prevent reordering of calls, a memory barrier between each call is needed for that. – Alexis Oct 13 '20 at 07:34