6.42 Когда обращаются к объекту 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, Предыдущее: Встроенные функции, Выше: Расширения языка C [Оглавление][Индекс]
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-5.5.0/gcc/Volatiles.html