2010-08-19 11 views
7
int main(void) 
{ 
    char four[4] = "four"; 
    return 0; 
} 

Quando compilato come un programma C++, G ++ riportachar four [4] = "four"; Quali sono le semantiche corrette per questa affermazione?

xxx.cpp: In funzione int main():

xxx.cpp: 3: errore: inizializzatore-stringa per array di i caratteri sono troppo lunghi

Quando è compilato un programma C, GCC non segnala alcun errore.

Mi sembra che l'assegnazione copi correttamente tutti i 4 byte nella variabile, come mi aspettavo.

Quindi la mia domanda si riduce a .....

è il comportamento osservato in C corretto o sto toccando un comportamento non definito da qualche parte, o è un'altra cosa?

+1

C'è una domanda molto simile con le risposte che corrispondono a questa domanda qui: http://stackoverflow.com/questions/3216462/initializing-char-arrays-in-a-way-similar-to-initializing-string-literals –

+0

Congratulazioni per averlo trovato. Sì. Discute un po 'il problema. – EvilTeach

risposta

22

Risposta breve: il codice è valido C, ma C++ non valido.

lungo risponderti:

"four" è in realtà 5 caratteri - si trova una \0 aggiunto lì per voi. Nella sezione 6.7.8 inizializzazione, punto 13, lo standard C dice:

An array of character type may be initialized by a character string literal, optionally enclosed in braces. Successive characters of the character string literal (including the terminating null character if there is room or if the array is of unknown size) initialize the elements of the array.

Così il \0 viene semplicemente ignorato nel programma quando viene compilato come C. C++ è trattare in modo diverso. In realtà, questo particolare caso è eliminato esplicitamente nelle specifiche C++ (sezione 8.5.2 array di caratteri, paragrafo 2):

There shall not be more initializers than there are array elements. [ Example:

char cv[4] = "asdf"; // error 

is ill-formed since there is no space for the implied trailing ’\0’ . — end example ]

+1

In C questo è valido, ma dovrebbe darti un avvertimento ad un certo livello. – Joel

+0

@Joel, non penso ci dovrebbe essere un avvertimento, lo standard sembra indicare che è completamente sicuro e ben definito. –

+0

Mentre sizeof ("four") è 5 byte, solo 4 byte vengono copiati nella variabile. – EvilTeach

2

La stringa "quattro" effettivamente contiene cinque byte: i quattro lettere più un byte zero (\ 0) come terminatore di stringa. È passato un po 'di tempo da quando ho scritto C o C++, ma suppongo che il compilatore C lo stia silenziosamente ignorando per qualsiasi motivo.

2

migliore sarebbe

char four[] = "four"; 
+0

Che fornisce un array di cinque caratteri in C e C++ e funziona perfettamente. –

+0

@David, solo se si * desidera * un array di cinque caratteri. Ma se non ti interessa, questo modo è sicuramente più gestibile. –

+0

Giusto, direi che non vorrai quasi mai char four [4] = "four". –

1

Quello che stai vedendo è una differenza tra C e C++. C ti permette di avere inizializzatori aggiuntivi, che vengono ignorati. C++ vieta questo: se si specifica una dimensione per una stringa (o array), lo deve essere sufficientemente grande da contenere tutti gli inizializzatori (incluso il terminatore NUL, nel caso di una stringa), oppure il codice è mal formato (standardizzato per "non è permesso - si aspetta che il compilatore lo respinga").

+0

No. Penso che il NUL extra sia trattato come un caso speciale. Se lo fai, char four [4] = "fiveX"; Si ottiene un errore in C. – EvilTeach

+0

@EvilTeach - Ricevo un avviso, non un errore, con il caso '" fiveX "'. –

+0

@EvilTeach (e Carl): Questo (in gran parte) ritorna ad una difficoltà con gli standard: richiedono una "diagnostica" per codice errato (ma il compilatore può ancora accettare il codice se così dovesse scegliere), ma dipende dal compilatore per definire ciò che è (o meno) una diagnostica. È anche tipico che siano necessarie bandiere specifiche per la conformità, quindi potresti non ottenerne nemmeno più di tanto. –

Problemi correlati