6.44 Когда обращается к переменной типа Volatile?
В C существует понятие переменных типа volatile. К ним обычно обращаются через указатели и они используются для доступа к аппаратуре или межпоточной коммуникации. Стандарт рекомендует компиляторам воздерживаться от оптимизации, касающейся доступа к переменным типа volatile, но оставляет за реализацией определение того, что представляет собой доступ к переменной типа volatile. Минимальное требование заключается в том, что на точке последовательности все предыдущие обращения к переменным типа volatile должны быть стабилизированы, а последующие обращения не должны произойти. Таким образом, реализация свободна переупорядочивать и объединять обращения к переменным типа volatile, происходящие между точками последовательности, но не может делать это для обращений через точку последовательности. Использование volatile не позволяет нарушать ограничение на обновление объектов несколько раз между двумя точками последовательности.
Обращения к переменным, не являющимся volatile, не упорядочены по отношению к обращениям к переменным типа volatile. Вы не можете использовать переменную типа volatile как барьер памяти для упорядочения последовательности записей в память, не являющуюся volatile. Например:
int *ptr = something; volatile int vobj; *ptr = something; vobj = 1;
Если переменные *ptr и vobj не могут быть алиасами, не гарантируется, что запись в *ptr произойдёт к моменту обновления vobj. Если вам нужна эта гарантия, необходимо использовать более сильный барьер памяти, например:
int *ptr = something;
volatile int vobj;
*ptr = something;
asm volatile ("" : : : "memory");
vobj = 1;
Скалярная переменная типа volatile считывается, когда к ней обращаются в контексте void:
volatile int *src = somevalue; *src;
Такие выражения являются rvalue, и GCC реализует это как чтение переменной типа volatile, на которую указывает указатель.
Присваивания также являются выражениями и имеют rvalue. Однако при присваивании скалярной переменной типа volatile, переменная типа volatile не перечитывается, независимо от того, используется ли rvalue выражения присваивания или нет. Если rvalue присваивания используется, значение равно тому, которое было присвоено переменной типа volatile. Например, нет чтения vobj во всех следующих случаях:
int obj; volatile int vobj; vobj = something; obj = vobj = something; obj ? vobj = onething : vobj = anotherthing; obj = (something, vobj = anotherthing);
Если вам нужно прочитать переменную типа volatile после того, как присваивание произошло, вы должны использовать отдельное выражение с промежуточной точкой последовательности.
Так как битовые поля не имеют отдельных адресов, битовые поля типа volatile могут быть неявным образом прочитаны при записи в них или при доступе к соседним битовым полям. Операции с битовыми полями могут быть оптимизированы таким образом, что соседние битовые поля читаются только частично, если они пересекают границу единицы хранения. По этим причинам не рекомендуется использовать битовые поля типа volatile для доступа к аппаратуре.
Далее: Использование ассемблерного языка с C, Предыдущее: Inline, Наверх: Расширения C [Оглавление][Индекс]
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-7.5.0/gcc/Volatiles.html