Droidum
Droidum

Reputation: 434

Unclear reason for assignment discards volatile qualifier

I have a pointer field in a struct that points to a linked list of struct instances.

struct myStruct {
    some fields...
    struct list_objects * volatile list;
}

According to my understanding I declare it like that to tell the compiler the pointer can change from other threads, so don't cache it.
Not the content of what list points to will change but the pointer will change. (otherwise volatile must be the first keyword right?)

Access to list is protected with a mutex so threads don't collide writing to this pointer.

A problem occurs when I read this pointer's address into a pointer to pointer.

struct list_objects **ptrToPtr = &myStructVariable->list;

I need the double pointer to assign another pointer into this variable or to walk the linked list.

The compiler issues a "assignment discards volatile qualifier" warning. I read about this warning and think I basically understood it but I don't understand why it appears here.
The address of this variable should never change. The content is volatile, but not the place where this content resides.

I guess I have a bad understanding of this matter. Please help me to sort this out.

Upvotes: 1

Views: 439

Answers (3)

Lundin
Lundin

Reputation: 213306

It is true that the volatile in this case is specific to the pointer and you should be able to do things like discarding the qualifier when copying the variable:

int* volatile vptr;
int* ptr = vptr;

Just as we can assign the value of a const int to an int.

However, that's not what your code does. It tries to point at the original type. For that you need a "pointer to volatile pointer to type". In your case this would be struct list_objects *volatile * ptrToPt (read right-to-left).

Alternatively, this would be fine too:

struct list_objects*  volatile vptr = ...;
struct list_objects*  ptr = vptr;
struct list_objects** pptr = &ptr;

But note that this take a copy of the original pointer, so if the original changes, then ptr will still contain the old address.

Upvotes: 2

Toby Speight
Toby Speight

Reputation: 30709

&myStructVariable->list is a pointer to a volatile pointer to struct list_objects.

So you need to declare ptrToPtr as

struct list_objects *volatile *ptrToPtr;
//                   ^^^^^^^^

Upvotes: 1

Eric Postpischil
Eric Postpischil

Reputation: 222302

You are correct that ptrToPtr will not change (if you perform no assignment to it), so it does not need to be volatile. However, *ptrToPtr may change, because it is effectively myStructVariable->list.

So your declaration should be struct list_objects * volatile * ptrToPtr = &myStructVariable->list;.

Upvotes: 4

Related Questions