2012-01-13 17 views
12

Me pregunto acerca de esta pieza de muestra de código:es `* - p 'realmente legal (bien formado) en C++ 03

int main() 
{ 
    char *p ; 
    char arr[100] = "Hello"; 
    if ((p=arr)[0] == 'H') // do stuffs 
} 

¿Es este código en realidad bien formado en C++ 03 ?

Mi argumento es que el efecto secundario de = se completa después de la siguiente secuencia de punto y dado que estamos accediendo el resultado de p=arr el código podría no estar bien formado, no existe una ordenación entre = y [] operaciones.

¿Es correcto?

El comportamiento está bien definido en C y en C++ 11. Este código en realidad se deriva de MySQL.

+19

El código en el título no aparece en la muestra de código que ha proporcionado. – porges

+3

¿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

+1

@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

Respuesta

24

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.

+2

Para cualquier lector futuro, consulte esta meta publicación: http://meta.stackexchange.com/questions/118996/where-did -all-the-comments-go-on-is-p-actually-legalwell-form-in-c03 – Mysticial

+1

Además, se puede encontrar una transcripción de los comentarios eliminados aquí: http://i.stack.imgur.com/ f4rIE.png –

Cuestiones relacionadas