Por supuesto que está bien definido.
No importa cuando tiene lugar la asignación p=arr
. No está evaluando p[0]
, está suscribiendo el resultado de (p=arr)
, que es el valor del puntero que se almacena en p
. Si se ha almacenado o no, no cambia el valor, y el valor se conoce independientemente de si se ha modificado p
.
Del mismo modo, en *--p
, no hay un comportamiento indefinido. Solo habría un comportamiento indefinido si se accediera a la misma variable dos veces, incluida al menos una escritura, entre los puntos de la secuencia. Pero solo se accede a p
una vez, como parte de --p
. No se vuelve a leer (*p
), el operador de desreferenciación se aplica al resultado de --p
que es un valor de puntero bien definido.
Ahora, esto sería un comportamiento indefinido:
void* a;
void* p = &a;
reinterpret_cast<void**>(p = &p)[0] = 0;
al igual que
int *pi = new int[5];
int i = **&++pi;
Debe quedar claro que el resultado de un preincremento no es una lectura desordenada con la escritura, porque afirmar que hay una carrera es afirmar que ++p
nunca se puede usar como un valor r, en cuyo caso debe ser independiente entre puntos de secuencia, y el incremento posterior se puede usar anuncio. No habría ninguna ventaja de tener tanto preincremento como incremento posterior en el idioma.
El código en el título no aparece en la muestra de código que ha proporcionado. – porges
¿Está '((a = b) + x)' bien definido? Si está bien definido, entonces '(p = arr) [0]' estaría bien definido también, porque es equivalente a '* ((p = arr) + 0)' – Nawaz
@Prasoon: de acuerdo con su argumento, 'int x = ++ i + n' invoca UB? Porque según usted, la razón debería ser: el efecto secundario de '++' se completa solo después del siguiente punto de secuencia y, dado que estamos accediendo al resultado de '++ i', es posible que el código no esté bien formado. ¿Lo es? – Nawaz