Arrays que no son lvalues ​​y restricción de puntos de secuencia.

En la norma ISO C99, las matrices que no son valores límicos siguen decayendo a los punteros, y pueden estar subíndilizadas, aunque pueden no modificarse o usarse después del siguiente punto de secuencia. ( fuente )

Entiendo que esta función permite la indexación de matrices en los casos en que una función devuelve una estructura que contiene una matriz, que no está permitida en C89 ( http://yarchive.net/comp/struct_return.html )

¿Me podría ayudar, por favor, a comprender por qué hay una restricción en el uso / modificación después del siguiente punto de secuencia?

Tenga en cuenta que el texto OP citado es de la documentación de GCC. El texto relevante de C99 para respaldar esa cita es:

C99 6.5.2.2/5

Si se intenta modificar el resultado de una llamada de función o acceder a él después del siguiente punto de secuencia, el comportamiento no está definido.

y también de la lista de cambios en el Prólogo:

conversión de matriz a puntero no limitada a lvalues

No tengo el texto de C89 para comparar, pero la descripción de conversión de matriz a puntero de C99 (6.3.2.1/3) no menciona ninguna restricción sobre la matriz como valor l. Además, la sección C99 sobre subíndices (6.5.2.1/2) habla sobre la expresión de subíndices como expresión postfix , tampoco menciona lvalues.


Considere este código:

struct foo { char buf[20]; }; struct foo foo(char const *p) { struct foo f; strcpy(f.buf, p); return f; } int main() { char *hello = foo("hello").buf; char *bye = foo("bye").buf; // other stuff... printf("%s\n", hello); printf("%s\n", bye); } 

¿A dónde apuntan los punteros hello y bye ? El propósito de esta cláusula es decir que el comstackdor no tiene que mantener todos los objetos devueltos en la memoria en algún lugar para hacer que esos punteros permanezcan válidos por tiempo indefinido.

En cambio, el hello solo es válido hasta el siguiente ; en este caso (o siguiente punto de secuencia en general). Esto deja al comstackdor libre para implementar estructuras devueltas por valor como un parámetro de puntero oculto, como describe Chris Torek en su excelente publicación, que puede ser “liberada” al final de la statement actual.

NÓTESE BIEN. La situación de C99 no es tan simple como se describe en la publicación de Chris, ya que lo siguiente tiene que funcionar:

 printf("%s %s\n", foo("hello").buf, foo("bye").buf); 

Sin embargo, mi instalación de gcc 4.8 parece ser correcta, funciona con -std=c99 y segfaults con -std=c89 .