我在结构中有一个指针字段,它指向结构实例的链接列表。
struct myStruct {
some fields...
struct list_objects * volatile list;
}
根据我的理解,我这样声明它是为了告诉编译器指针可以从其他线程更改,因此请不要缓存它。
list
指向的内容不会改变,但指针会改变。 (否则,volatile必须是第一个关键字吗?)
对list
的访问受到互斥量的保护,因此线程不会在写入此指针时发生冲突。
当我将该指针的地址读入指向指针的指针时,会发生问题。
struct list_objects **ptrToPtr = &myStructVariable->list;
我需要双指针将另一个指针分配给该变量或遍历链表。
编译器发出“分配放弃易失性限定符”警告。我阅读了此警告,并认为我基本上理解了该警告,但我不明白为什么它会出现在这里。 此变量的地址永远不会更改。内容是易变的,但内容不可变。
我想我对此事认识不好。请帮我解决这个问题。
答案 0 :(得分:4)
您是正确的,ptrToPtr
不会更改(如果您未对其进行赋值),因此它不必是易变的。但是,*ptrToPtr
可能会发生变化,因为它实际上是myStructVariable->list
。
因此,您的声明应为struct list_objects * volatile * ptrToPtr = &myStructVariable->list;
。
答案 1 :(得分:2)
在这种情况下,volatile
确实是特定于指针的,并且您应该能够执行以下操作,例如在复制变量时丢弃限定符:
int* volatile vptr;
int* ptr = vptr;
就像我们可以将const int
的值分配给int
一样。
但是,这不是您的代码所要做的。它试图指向原始类型。为此,您需要一个“指向可变指针的指针”。您的情况是struct list_objects *volatile * ptrToPt
(从右到左阅读)。
或者,也可以:
struct list_objects* volatile vptr = ...;
struct list_objects* ptr = vptr;
struct list_objects** pptr = &ptr;
但是请注意,这需要原始指针的副本,因此,如果原始指针发生更改,则ptr
仍将包含旧地址。
答案 2 :(得分:1)
&myStructVariable->list
是指向struct list_objects
的 volatile指针的指针。
因此您需要将ptrToPtr
声明为
struct list_objects *volatile *ptrToPtr;
// ^^^^^^^^