2012-01-14 18 views
9

This answer of mine generado algunos comentarios afirmando que el siguiente constructo no es legal C/C++:¿Es esto legal C/C++? `Int * p = (int []) {1,2,3};`

void f (int* a) ; 
f ((int[]){1,2,3,4,0}) ; 

(ver this ideone link para una completa programa). Pero no pudimos resolver el problema. ¿Alguien puede arrojar algo de luz sobre esto? ¿Qué tienen que decir los diversos estándares?

+0

Creo que @Nicol Bolas tiene razón, que comentó sobre su publicación. No todo lo que funciona, es válido. Eso es en realidad realmente el caso. Diría que el fragmento de tu comentario da como resultado un "comportamiento indefinido". Entonces, si quiere demostrarle que es legal, debe buscar/buscar dentro del estándar c/C++/C++ 11. – poitroae

+0

@Michael: No quiero probar que es legal, solo quiero saber si es legal o no. Los comentarios a mi publicación (incluidos mis comentarios) son solo opiniones. – TonyK

+0

¿Por qué es un comportamiento indefinido? –

Respuesta

9

Es válido C99 por lo que puedo decir, eso es pasar un compuesto literal.

estándar El C99 tiene esto como un ejemplo (§6.5.2.5/9):

Ejemplo 1 La definición ámbito de archivo

int *p = (int []){2, 4}; 

inicializa p para apuntar a la primer elemento de una matriz de dos ints, el primero tiene el valor dos y el segundo, cuatro. Se requiere que las expresiones en este literal compuesto sean constantes. El objeto sin nombre tiene una duración de almacenamiento estática.

Tenga en cuenta que la cosa (int []) no está aquí.

Esto no es una construcción C++ válida, sin embargo, los literales compuestos no son parte del estándar C++ (C++ 11 incluido). Algunos compiladores lo permiten como una extensión. (GCC, pasan -Wall -pedantic para obtener un diagnóstico al respecto. IBM xlC allows it as an extension too.)

+2

Tenga en cuenta que el objeto de matriz tiene duración de almacenamiento estático solo si está en el alcance del archivo, como en el ejemplo. Si aparece dentro de una definición de función, entonces tiene una duración de almacenamiento automática asociada con el bloque adjunto (es decir, el objeto y cualquier puntero a este se vuelven inválidos cuando la ejecución alcanza el '' 'adjunto). Esto es diferente a los literales de cadena, que siempre tienen una duración de almacenamiento estático. –

+0

¡Gracias! Eso parece cubrir todo. – TonyK

+0

¿Qué duración de almacenamiento sería 'char * p = (char []) {'s', 't', 'r', 'i', 'n', 'g', 0}' tener? – hirschhornsalz

-1

Bueno, creo que es válido de acuerdo con C++ 11. Sección 5.2:

postfix-expression: 
    ... 
    typename-specifier (expression-listopt) 
    simple-type-specifier braced-init-list 
    typename-specifier braced-init-list 
    ... 
expression-list: 
    initializer-list 

EDIT: Después de leer un poco más que llegó a la conclusión que en realidad es inválida , porque no se puede usar la expresión de sufijo así. Debería haber alguna expresión primaria.

+1

Puede citar. Y no veo nada allí que lo haga válido. –

+0

El fragmento que publicó no coincide con la pregunta. Si está interesado, este tipo de sintaxis de molde está en §5.4, no §5.2.También debe leer las conversiones permitidas y descubrirá que no está autorizado a convertir en un tipo de matriz. –

+0

@R. Martinho Fernandes: Ahora estoy confundido. Pensaría que 'typename-specifier braced-init-list' podría escribir eq. como 'tipo {1, 2, 3, 4}', pero gcc no me permite hacer esto. ¿Se supone que esto es solo para estructuras, o estoy completamente equivocado? – stativ

1

La expresión se pasa como argumento de la función es un ejemplo de un compuesto literal. Estos son legales en C99, pero no en C++ 98.

Consulte, por ejemplo, la sección 6.4.4 "Constantes" y 6.8 "Declaraciones y bloques" en N897 "A draft rationale for the C99 standard." Consulte también this section de la documentación de GCC.