我似乎總體上對volatiles
有一個合理的理解,但有一個看似不明確的情況,我不確定每個標準應該如何工作。我已經閱讀了C99的相關部分以及SO上的十幾個或更多相關帖子,但無法找到這種情況下的邏輯或解釋這種情況的地方。賦值表達式和volatile
假設我們有這樣的一段代碼:
int a, c;
volatile int b;
a = b = 1;
c = b += 1; /* or equivalently c = ++b; */
應該a
這樣的評價:
b = 1;
a = b; // volatile is read
或像這樣:
b = 1;
a = 1; // volatile isn't read
?
同樣,應該c
這樣的評價:
int tmp = b;
tmp++;
b = tmp;
c = b; // volatile is read
或像這樣:
int tmp = b;
tmp++;
b = tmp;
c = tmp; // volatile isn't read
?
在簡單的情況下,如a = b; c = b;
事情很清楚。但是上面的那些呢?
基本上,問題是,究竟是什麼「表達有分配後左操作數的值」是指在C99的6.5.16c3當對象是揮發性?:
賦值運算符商店由左邊的操作數指定的對象中的值。一個賦值表達式在賦值之後具有左操作數 的值,但不是左值。
它是否意味着要額外讀取volatile以產生賦值表達式的值?
UPDATE:
所以,這裏的窘境。
如果未從易失性物體的額外的讀獲得了「分配後的對象的值」,則編譯器作出的假設是,揮發性對象b
:
- 是能夠保持任意
int
值寫入它,它可能不是(比方說,0位是硬連線到0,這與硬件寄存器,這是不尋常的事情,我們應該使用揮發物) - 不能改變之間的指定寫入發生時的時間點和獲取表達式值的時間點(並且可能是一個問題與硬件寄存器)
的,因爲所有的和,表達值,如果沒有從所述易失性物體的額外的讀得到,不會產生揮發性物體,其標準權利要求應該是這樣的值。
這兩個假設似乎都不符合易失物體的性質。
如果OTOH是從所述易失性對象的額外隱含讀取中獲得「賦值之後的對象的值」,那麼評估具有易失性左操作數的賦值表達式的副作用取決於是否使用表達式值或者不是或完全是任意的,這將是一個奇怪的,意想不到的和記錄不完善的行爲。
我希望賦值給volatile並不意味着在store之後進行讀取(無論賦值的值是否在其他地方使用都無關緊要)。這意味着標準對volatile變量的映射硬件寄存器定義爲volatile變量(或指向volatile的變量)不會有幾乎所有人都依賴的語義。 –
@MichaelBurr好點。 –