[英]pointers in a volatile struct in C
說我有一個結構
typedef struct A{
int a1;
int *a2;
}A_t;
現在如果我聲明這個結構的實例是volatile的 -
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
是非易失性的並且trialptr->a2
是易失性的?
ptrToField
也應該是易變的嗎?
使用struct A
的定義,成員a2
指向的東西不會被聲明為volatile
。 這給定的實例struct A
是volatile
意味着其成員a2
(指針)是volatile
,但不是說那東西它指向的是volatile
。 這是int * volatile
(相當於實際情況)和volatile int *
之間的區別。
你描述的初始化......
int *ptrToField = ptrToTrial->a2;
...使用指針 ptrToTrial->a2
的值初始化ptrToField
。 因為ptrToTrial
指向volatile
對象,所以程序必須從主內存加載指針(該易失性對象的成員)。 因為指向的東西不是(聲明為)易失性,所以沒有信息丟失,並且在將ptrToField
的目標類型聲明為普通int
沒有(新)風險。 當然,將ptrToField
本身聲明為volatile是沒有優勢的。
還要注意,如果不清楚,變量ptrToField
的名稱與您放置它的用途不一致。 您沒有初始化它以指向您的struct
的成員; 相反,您將其初始化為struct
成員的副本 。
編譯器是否知道
prtToField
在沒有明確提及的情況下是易失性的,因為它是通過易失性的ptrToTrial
訪問的?
不需要行使它可能具有的任何知識,並且在任何情況下,知識的范圍可能非常有限。 它知道該變量是如何初始化的,但可能很難預測其后的值何時以及如何被修改。 在任何情況下,未聲明的變量類型所攜帶的任何信息都與程序的標准C語義無關。
不應該編譯器也抱怨指針p - 因為p是非易失性的並且trialptr-> a2是易失性的?
不,因為雖然trialptr->a2
是易失性的,但讀取其值 (在某個給定時間點)並將該值分配給另一個變量沒有問題。 對象值是位模式,它們既不是易失性也不是非易失性 - 這是它們存儲的特征,通過它們被訪問的左值進行通信。
請注意int *a2;
在你的struct A
不是易變的。 所以
int *ptrToField = ptrToTrial->a2;
ptrToField
volatile
。
trailFunction(ptrToTrial)
獲取錯誤,因為函數trailFunction
需要A_t *trialptr
,但是你傳遞volatile A_t*
,它顯然是編譯錯誤。
最后:
function trialFunction(volatile A_t *trialptr)
{
int *p = trialptr->a2;
}
編譯是可以的,因為a2
的類型是int*
。
我首選的位置通常在指針聲明中。 這樣,結構中的所有寄存器將被編譯器視為易失性,但是有可能使所述結構的其他(例如基於RAM的陰影)實例不是易失性的,因為它們實際上不是硬件寄存器下。
因此,我建議你使用:
typedef volatile struct
祝你今天愉快
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.