Конечно, это четко определено.
Не имеет значения, когда имеет место задание p=arr
. Вы не оцениваете p[0]
, вы подписываете результат (p=arr)
, который является значением указателя, которое хранится в p
. Независимо от того, сохранено ли оно или нет, значение значения не изменяется, и значение известно независимо от того, было ли изменено значение p
.
Аналогичным образом, в *--p
нет неопределенного поведения. Было бы неопределенное поведение, если бы к одной и той же переменной дважды обращались, включая по крайней мере одну запись, между точками последовательности. Но p
доступен только один раз, как часть --p
. Он не читается снова (*p
), оператор разыменования применяется к результату --p
, который является четко определенным значением указателя.
Теперь это будет определено поведение:
void* a;
void* p = &a;
reinterpret_cast<void**>(p = &p)[0] = 0;
, как бы
int *pi = new int[5];
int i = **&++pi;
Должно быть ясно, что результат прединкремента не читал неупорядоченный с записью, потому что утверждать, что есть гонка, состоит в том, чтобы утверждать, что ++p
никогда не может использоваться как rvalue, и в этом случае он должен стоять отдельно между точками последовательности, а пост-приращение можно использовать inste объявление. Не было бы никакого преимущества иметь как предварительный приращение, так и пост-прирост в языке.
Код в заголовке не указан в приведенном вами образце кода. – porges
Является ли '((a = b) + x)' корректным? Если он корректно определен, то также будет корректно определен '(p = arr) [0]', поскольку он эквивалентен '* ((p = arr) + 0)' – Nawaz
@Prasoon: согласно вашему аргумент, 'int x = ++ i + n' вызывает UB? Потому что, по вашему мнению, причина должна быть: побочный эффект '++' завершается только после следующей точки последовательности, и поскольку мы получаем результат «++ i», код может быть не совсем корректным. Это? – Nawaz