假设我有一个结构
typedef struct A{
int a1;
int *a2;
}A_t;
现在,如果我将此结构的实例声明为易变的 -
volatile A_t trial;
我使用一个 volatile 指针来访问这个 volatile 结构。
volatile A_t *ptrToTrial = &trial;
如果我尝试这样做:
int *ptrToField = ptrToTrial->a2;
ptrToField
也应该是可变的吗?编译器是否知道 prtToField
是易变的而不明确提及,因为它是通过易变的 ptrToTrial
访问的?
还有如果有一个函数——
function trialFunction(A_t *trialptr)
{
int *p = trialptr->a2;
}
如果我们用上面声明的 volatile ptr 调用这个函数 -
trailFunction(ptrToTrial)
我得到一个错误:volatile A_t* is incompatible with parameter of type A_t
。
因此,如果我更改函数定义以包含 volatile
,我不会看到错误。
function trialFunction(volatile A_t *trialptr)
{
int *p = trialptr->a2;
}
编译器不应该也提示指针 p
- 因为 p
是非 volatile 的而 trialptr->a2
是 volatile 的吗?
最佳答案
Should
ptrToField
be volatile as well?
根据您对 struct A
的定义,成员 a2
指向的内容未声明为 volatile
。 struct A
的给定实例是volatile
意味着它的成员a2
(指针)是volatile
,但是不是它指向的东西是volatile
。这就是int * volatile
(相当于实际情况)和volatile int *
的区别。
你描述的初始化...
int *ptrToField = ptrToTrial->a2;
... 使用指针 ptrToTrial->a2
的值初始化ptrToField
。因为 ptrToTrial
指向一个 volatile
对象,所以程序必须从主内存加载指针(该 volatile 对象的成员)。因为指向的东西不是(声明为) volatile 的,但是,没有信息丢失,也没有(新的)风险是将 ptrToField
的目标类型声明为普通 所固有的整数
。当然,将 ptrToField
本身声明为 volatile 没有任何优势。
另请注意,如果不清楚,您的变量 ptrToField
的名称与您对它的使用不一致。您没有将其初始化为指向您的 struct
的成员;相反,您将其初始化为 struct
成员的副本。
Would the compiler know that
prtToField
is volatile without explicit mention because it is accessed throughptrToTrial
which is volatile?
它不需要行使它可能拥有的任何此类知识,而且在任何情况下,这些知识的范围都可能非常有限。它知道该变量是如何初始化的,但可能很难预测此后何时以及如何修改其值。在任何情况下,任何未由声明的变量类型携带的信息与程序的标准 C 语义无关。
Shouldn't the compiler also complain about the pointer p - because p is non-volatile and trialptr->a2 is volatile?
不,因为虽然 trialptr->a2
是易变的,但读取它的值(在给定的时间点)并将该值赋给另一个没有问题多变的。对象值是位模式,它们既不是 volatile 的也不是非 volatile 的——这是它们存储的一个特征,通过访问它们的左值进行通信。
关于c - C中 volatile 结构中的指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37971299/