6.46 Когда происходит доступ к объекту типа 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;
Такие выражения являются правыми значениями, и GCC реализует это как чтение volatile объекта, на который указывает указатель.
Присваивания также являются выражениями и имеют правое значение. Однако при присваивании скалярному volatile объекту, volatile объект не перечитывается, независимо от того, используется ли правое значение выражения присваивания или нет. Если правое значение присваивания используется, значение является тем, которое присвоено volatile объекту. Например, нет чтения vobj во всех следующих случаях:
int obj; volatile int vobj; vobj = something; obj = vobj = something; obj ? vobj = onething : vobj = anotherthing; obj = (something, vobj = anotherthing);
Если вам нужно прочитать volatile объект после того, как присвоение произошло, вы должны использовать отдельное выражение с промежуточной точкой последовательности.
Поскольку битовые поля не являются индивидуально адресуемыми, битовые поля типа volatile могут быть неявным образом прочитаны при записи или при доступе к смежным битовым полям. Операции с битовыми полями могут быть оптимизированы таким образом, что смежные битовые поля читаются только частично, если они пересекают границу хранилища. По этим причинам не рекомендуется использовать volatile битовые поля для доступа к аппаратуре.
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-11.4.0/gcc/Volatiles.html