2012-10-01 17 views
17

Estoy tratando de descifrar a note que condujo a un cambio entre C99 y C11. El cambio propuesto en dicha nota terminó en de 6.2.4 C11: 8, a saber:Vida útil de los objetos temporales en C11 vs C99

una expresión no lvalue con estructura o unión tipo, donde la estructura o unión contiene un miembro con tipo de matriz (incluyendo , recursivamente, miembros de todas las estructuras y uniones contenidas) se refiere a a un objeto con duración de almacenamiento automática y duración temporal. Su duración comienza cuando se evalúa la expresión y su valor inicial es el valor de la expresión. Su tiempo de vida finaliza cuando finaliza la evaluación de la expresión completa que contiene o el declarador completo. Cualquier intento de modificar un objeto con duración temporal da como resultado comportamiento indefinido.

Entiendo por qué fue necesario el cambio (se puede encontrar alguna discusión en here. Tenga en cuenta que la discusión se remonta a antes de C11). Sin embargo, lo que no entiendo es una observación lateral que Clark Nelson hecha por escrito su nota:

Tenga en cuenta que este enfoque, además, declara un ejemplo como este , que fue conformando bajo C99, a no ser conforme:

struct X { int a[5]; } f(); 
int *p = f().a; 
printf("%p\n", p); 

entiendo por qué este ejemplo no es conforme con arreglo a C11. Lo que específicamente no entiendo es cómo se está ajustando bajo C99. Y, si está definido en C99, ¿qué se supone que debe hacer entonces, imprimir de manera definida el valor de un puntero colgante?

+0

No entiendo cómo es que no cumple con C99 o C11, ya que no intenta modificar el objeto con una vida temporal o acceder a él una vez que finaliza la vida útil. El valor exacto del puntero que imprime es obviamente desconocido, pero debe imprimir algún valor de puntero. –

+1

@ChrisDodd La razón por la que no está definido en C11 es que contraviene 6.2.4: 2, específicamente "El valor de un puntero se vuelve indeterminado cuando el objeto al que apunta (o simplemente pasado) llega al final de su vida útil". Es un comportamiento moralmente indefinido para acceder a contenidos indeterminados (se enumera como tal en J.2: "El valor de un puntero a un objeto cuya vida se ha terminado se utiliza (6.2.4)", aunque el cuerpo normativo real es un poco más ambiguo). C99 es muy similar a ese respecto. La única diferencia que veo es que p no ** se vuelve ** indeterminado porque nunca está determinado. –

Respuesta

7

Según tengo entendido, en C99, el grano de vida más fino para un objeto es el bloque. Por lo tanto, mientras que 6.5.2.2 (y algunos otros § mencionados en la nota a la que se refiere) dice específicamente que no puede acceder al valor devuelto después del siguiente punto de secuencia, técnicamente su dirección es no indeterminada hasta después de haber dejado el bloque de inclusión (la razón por la que debería tener algo de espacio de almacenamiento reservado para un objeto inaccesible queda como ejercicio para el lector). Por lo tanto, algo así como

struct X { int a[5]; } f(); 
int *p; 
{ p = f().a; } 
printf("%p\n", p); 

no está definido ni en C99 ni en C11. En C11, la noción de "vida temporal", que no existe en C99, permite considerar que el puntero se vuelve indeterminado tan pronto como termina la expresión completa.

+0

"el grano de vida más fino para un objeto es el bloque" De acuerdo, para objetos con duración de almacenamiento automático (C99 6.2.4: 5) –

Cuestiones relacionadas