Ответ 1
Конечно, он четко определен.
Не имеет значения, когда выполняется присвоение p=arr
. Вы не оцениваете p[0]
, вы подписываете результат (p=arr)
, который является значением указателя, которое хранится в p
. Независимо от того, сохранено ли оно еще, значение значения не изменяется, и значение известно независимо от того, было ли еще изменено p
.
Аналогично, в *--p
не существует поведения undefined. Было бы только поведение undefined, если бы к одной и той же переменной дважды обращались, включая хотя бы одну запись, между точками последовательности. Но p
доступен только один раз, как часть --p
. Он не читается снова (*p
), оператор разыменования применяется к результату --p
, который является четко определенным значением указателя.
Теперь это будет undefined поведение:
void* a;
void* p = &a;
reinterpret_cast<void**>(p = &p)[0] = 0;
как и
int *pi = new int[5];
int i = **&++pi;
Должно быть ясно, что результат преинкремента не считается неупорядоченным с записью, потому что утверждать, что существует раса, заключается в утверждении, что ++p
никогда не может использоваться как rvalue, и в этом случае он должен автономно между точками последовательности, и вместо этого может использоваться пост-приращение. Не было бы никакого преимущества иметь как предварительный приращение, так и пост-инкремент на языке.