2012-01-14 4 views
9

This answer of mine generato alcuni commenti sostenendo che il seguente costrutto non è legale C/C++:È legale questo C/C++? `Int * p = (int []) {1,2,3};`

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

(vedi this ideone link per una completa programma). Ma non siamo stati in grado di risolvere il problema. Qualcuno può far luce su questo? Che cosa hanno da dire i vari standard?

+0

Penso che @Nicol Bolas abbia ragione, che ha commentato il tuo post. Non tutto ciò che funziona è valido. Questo è in realtà molto spesso il caso. Direi che lo snippet nel tuo commento risulta in "comportamento indefinito". Quindi se vuoi dimostrargli che è legale, devi cercare/cercare all'interno dello standard c/C++/C++ 11. – poitroae

+0

@ Michael: Non voglio dimostrare che è legale, voglio solo sapere se è legale o no. I commenti al mio post (compresi i miei commenti) sono solo opinioni. – TonyK

+0

Perché è un comportamento indefinito? –

risposta

9

È valido C99 per quanto posso dire - che sta passando un letterale composto.

serie La C99 ha come esempio (§6.5.2.5/9):

ESEMPIO 1 La definizione nell'ambito di file

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

inizializza p per puntare al primo elemento di una matrice di due interi, il primo con valore due e il secondo quattro. Le espressioni in questo composto letterale devono essere costanti. L'oggetto senza nome ha una durata di archiviazione statica.

Si noti che la cosa (int []) non è un cast qui.

Questo non è un costrutto C++ valido, i letterali composti non fanno parte dello standard C++ (incluso C++ 11). Alcuni compilatori lo consentono come un'estensione. (GCC fa, passa -Wall -pedantic per ottenere una diagnostica della medesima. IBM XLC allows it as an extension too.)

+2

Si noti che l'oggetto array ha durata di archiviazione statica solo se è nell'ambito di file, come nell'esempio. Se appare all'interno di una definizione di funzione, ha una durata di memorizzazione automatica associata al blocco che la racchiude (cioè, l'oggetto e qualsiasi puntatore ad esso diventano non validi quando l'esecuzione raggiunge l'allegato '}'). A differenza dei letterali stringa, che hanno sempre una durata di archiviazione statica. –

+0

Grazie! Questo sembra coprire tutto. – TonyK

+0

Quale durata di memorizzazione sarebbe 'char * p = (char []) {'s', 't', 'r', 'i', 'n', 'g', 0}' hanno? – hirschhornsalz

-1

Bene, penso che sia valido secondo C++ 11. Sezione 5.2:

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

EDIT: Dopo un po 'di più la lettura mi è venuto a conclusione che in realtà è valida, perché non è possibile usare l'espressione postfissa del genere. Ci dovrebbe essere qualche espressione primaria.

+1

Puoi citare. E non vedo nulla che lo renda valido. –

+0

Lo snippet che hai postato non corrisponde alla domanda. Se sei interessato, questo tipo di sintassi cast è in §5.4 non §5.2.Dovresti anche leggere le conversioni consentite e scoprirai che non ti è permesso eseguire il cast in un tipo di array. –

+0

@R. Martinho Fernandes: Ora sono confuso. Penso che 'typename-specifier braced-init-list' potrebbe scrivere eq. come 'sometype {1, 2, 3, 4}', ma gcc non mi permette di farlo. Questo è supposto solo per le strutture o ho completamente torto? – stativ

1

L'espressione passata come argomento alla funzione è un esempio di un letterale composto. Questi sono legali in C99, ma non in C++ 98.

Vedere ad esempio la sezione 6.4.4 "Costanti" e 6.8 "Dichiarazioni e blocchi" in N897 "A draft rationale for the C99 standard." Vedere anche this section della documentazione GCC.