C11 6.7.3 Типовые классификаторы, параграф 7, гласят:
Объект, который имеет изменчивый тип, может быть изменен способами, неизвестными реализации или имеющими другие неизвестные побочные эффекты. Поэтому любое выражение, относящееся к такому объекту, должно оцениваться строго в соответствии с правилами абстрактной машины, как описано в 5.1.2.3.
В следующем примере объект, доступ к которому в третьей строке относится к указанному выше правилу?
int x;
volatile int *p = &x;
*p = 42;
Другими словами, имеет ли тот факт, что lvalue *p
имеет тип volatile int
, означает, что к нему относится изменчивый объект, или тот факт, что p
указывает на энергонезависимый объект x
, означает, что компилятор может оптимизировать эти знания и опустить нестабильный доступ?
Поскольку это может представлять интерес, конкретный случай использования, который меня интересует, выходит за рамки простого C; он включает атомизацию для синхронизации потоков с использованием конструкций pre-C11 (которые могут быть встроенными asm или просто считаться черным ящиком) для атомного сравнения и замены со следующей идиомой:
do {
tmp = *p;
new = f(tmp);
} while (atomic_cas(p, tmp, new) != success);
Здесь указатель p
будет иметь тип volatile int *
, но меня беспокоит то, что происходит, когда фактически выделенный объект является энергонезависимым, в частности, может ли компилятор преобразовать единственный доступ к *p
из tmp = *p
в два обращения в следующем виде:
do {
new = f(*p);
} while (atomic_cas(p, *p, new) != success);
что, очевидно, сделает код неправильным. Таким образом, цель состоит в том, чтобы определить, действительно ли все такие объекты с заостренными предметами должны быть volatile int
.