22

I am looking at the following code:

inline void* interlocked_read_acquire(void* volatile* x);

and am wondering why not just a volatile void* as an argument. In general what is the semantics or definition of a volatile*? I am also making the assumption that you could use the volatile* qualifier with any other type besides void. Is that correct?

Matthew Hoggan
  • 7,402
  • 16
  • 75
  • 140
  • That seems valid but I am not sure how to read it, so that is why I asked. – Matthew Hoggan Nov 28 '14 at 03:56
  • 1
    My guess for the downvote would be that someone only read the question title and assumed it was a no-research question about what `void` or `volatile` mean in isolation. – Matt Coubrough Nov 28 '14 at 04:03
  • 2
    @vsoftco surely that's rather an over-estimate (amongst people following the c++ tag anyway) - `volatile` is commonly known and so is the meaning of simple pointer declarations , so even if this specific combination hadn't been seen before it can be worked out – M.M Nov 28 '14 at 05:15
  • @MattMcNabb agree, maybe I should've changed the percentage, but when you first bump into it, and someone asks you "tell me what the heck is this", I bet most people won't be able to respond in 5 seconds. Or maybe you would be able to, however I have to first remind myself what `volatile` means, then remind myself the multiple pointer definition stuff. But in any case, I wouldn't have downvoted such a question. – vsoftco Nov 28 '14 at 05:16

4 Answers4

21

Use cdecl or the clockwise spiral rule to decipher C-style declarations :

void* volatile* x
  • declares x as pointer to volatile pointer to void

which is different from :

volatile void* x
  • declare x as pointer to volatile void
quantdev
  • 23,517
  • 5
  • 55
  • 88
  • 2
    quantdev, does `volatile void` even make sense? Or does it in casts? – vsoftco Nov 28 '14 at 05:23
  • 2
    @vsoftco: it makes sense - you can add but not remove `volatile` during a `static_cast` (you'd need to also use `const_cast`), so ensuring the `volatile void*` is `volatile` helps prevent accidental removal of volatility when accessing the pointed-to object. – Tony Delroy Nov 28 '14 at 06:46
  • volatile void makes sense if you assume that a void* doesn't point to a void, it points to something with a real type but you don't know which type. So "volatile void*" means "could be volatile int*, could be volatile double*, could be volatile some struct*..." – gnasher729 Nov 28 '14 at 17:35
10

wondering why [void* volatile* and] not just a volatile void*...?

They're different things.

  • void* volatile* is a pointer to a volatile (void*) (so dereferencing and accessing the volatile void* is possible without casting, but would just give you the address of some as-yet unspecified thing in memory)

  • volatile void* is a pointer to a volatile void (so you must cast to a type like say volatile int* or volatile My_Class* before dereferencing)

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
7

void * ptr1; means that ptr1 is a variable whose type is void *. This type indicates a "generic pointer" - it points to some memory location but contains no type information what what is in that location.

void * volatile ptr2; means that the variable ptr2 is also a generic pointer, but ptr2 is also volatile. The keyword volatile is called a cv-qualifier and it has the same grammar rules as const.

The meaning of a volatile variable is that when some other code says ptr2, the compiler cannot optimize that out; it must read or write the memory location where ptr2 is stored; it must allow for the possibility that some external process is also reading or writing that location.

Finally, void * volatile *x is something that can point to ptr2. For example we could have void * volatile * x = &ptr2; . If we then write *x = NULL; for example, then *x has type void * volatile which has the same implications as we just looked at for ptr2.

The compiler would complain if you omitted the qualifier, e.g. void * *y = &ptr2; . This is because the expression *y would then have type void * (non-volatile) so the compiler might perform optimizations around it, however this is incorrect behaviour because ptr2 does not permit those optimizations. (You may recognize that "volatile-correctness" is the same sort of thing as const-correctness).

M.M
  • 138,810
  • 21
  • 208
  • 365
-1

volatile is an add-on property, you can first remove it to read from

void* volatile* x

to:

void* *x

This is very familiar. For example, an array of malloc-ed memory pointers. And you won't get confused with

volatile void*

which is reduced to

void* x.