2010-07-09 9 views
5

Supponiamo che abbia seguente inizializzazione di un array di char:inizializzazione array di caratteri in un modo simile a inizializzare stringhe

char charArray[]={'h','e','l','l','o',' ','w','o','r','l','d'}; 

e ho anche dopo l'inizializzazione di una stringa letterale:

char stringLiteral[]="hello world"; 

L'unica differenza tra il contenuto del primo array e la seconda stringa è che la seconda stringa ha un carattere null alla sua fine.

Quando si tratta di inizializzare un array di caratteri, esiste una macro o qualcosa che ci permetta di inserire il nostro testo di inizializzazione tra due virgolette doppie ma dove l'array non ottiene un carattere di terminazione null aggiuntivo?

Non ha senso per me che quando un carattere nullo terminante non è necessario, dovremmo usare la sintassi dell'inizializzazione menzionata per la prima volta e scrivere due virgolette singole per ogni carattere nel testo inizializzatore, così come i segni virgule separare i personaggi.

Devo aggiungere che quando voglio avere un array di caratteri, dovrebbe anche essere ovvio che non voglio usarlo con funzioni che si basano su stringhe letterali insieme al fatto che nessuna delle funzionalità in cui si utilizza la stringa risultati letterali, è nella mia considerazione.

Sono grato per le vostre risposte.

+0

@ Michael - è un requisito negli standard C e C++. – Steve314

+1

Il * PROBLEMA * che affronterai è che "le stringhe tra virgolette" sono richieste dalla lingua per terminare NUL. – torak

risposta

0

avrei potuto trovato un modo per fare quello che voglio anche se non è direttamente quello che volevo, ma probabilmente ha lo stesso effetto.
prima considerare due seguenti classi:

template <size_t size> 
class Cont{ 
public: 
    char charArray[size]; 
}; 
template <size_t size> 
class ArrayToUse{ 
public: 
    Cont<size> container; 
    inline ArrayToUse(const Cont<size+1> & input):container(reinterpret_cast<const Cont<size> &>(input)){} 
}; 

Prima di procedere, si potrebbe desiderare di andare here e dare un'occhiata a costruttori di espressione costanti e tipi di inizializzazione.
Ora guardate seguente codice:

const Cont<12> container={"hello world"}; 
ArrayToUse<11> temp(container); 
char (&charArray)[11]=temp.container.charArray; 

testo infine di inizializzazione è scritto tra le due citazioni doppie.

+0

Assicurarsi di schizzare alcuni commenti attorno a tale costrutto. Come avrete già intuito con altre risposte e commenti, ** not ** avere un terminante '\ 0' è un concetto piuttosto insolito e dovrebbe venire con i segnali di avvertimento appropriati. – DevSolar

+0

@DevSolar: apprezzato – Pooria

3

Non c'è modo di fare quello che vuoi. Il primo modo di inizializzare la matrice specifica gli inizializzatori separati per ciascun carattere, il che consente di escludere esplicitamente il carattere '\ 0'. Il secondo sta inizializzando un array di caratteri da una stringa di caratteri, che in C/C++ viene sempre terminata da un carattere nullo.

EDIT: corretto: 'puntatore carattere' -> 'array di caratteri'

+2

In realtà, non credo che il secondo caso stia inizializzando un puntatore a una stringa di caratteri. La sua creazione di un array e inizializzazione dei contenuti in base al contenuto della stringa. E sì, la differenza conta davvero. – torak

+0

non ho mai notato il concetto di "inizializzatori di caratteri separati", grazie – Pooria

0

La risposta di base è che la stragrande maggioranza degli array di caratteri sono stringhe - in C, le stringhe sono zero finale. C++ ha ereditato quella convenzione. Anche quando quel nulla non è necessario, il più delle volte non è un problema lasciarlo comunque.

Le macro non sono abbastanza potenti per fare quello che vuoi. I modelli sarebbero, eccetto che non hanno alcuna gestione della stringa in fase di compilazione.

Solitamente, quando la gente vuole mescolare byte numerici e letterali stringa nella stessa sequenza char-array, usano una stringa letterale ma utilizzano carattere esadecimale sfugge come \xFF.

6

è consentito in C per dichiarare la matrice come segue, che inizializzarlo senza copiare la terminazione '\0'

char c[3] = "foo"; 

Ma è illegale in C++. Non sono a conoscenza di un trucco che lo consentirebbe per C++. Il ++ standard C dice ancora

Razionale: Quando questi array non terminati sono manipolati dalle routine stringa standard, esiste la possibilità di grande catastrofe.
Effetto sulla funzione originale: eliminazione di funzionalità semanticamente ben definite.
Difficoltà di conversione: trasformazione semantica. Gli array devono essere dichiarati un elemento più grande per contenere la stringa che termina '\ 0'.
Quanto ampiamente utilizzato: Di rado. Questo stile di inizializzazione dell'array è considerato uno stile di codifica scadente.

+1

, trovo la tua risposta un po 'confusa. 'char c [4] =" pippo ";' mette il carattere nullo giusto? Questo è ancora lo stile di programmazione povero a cui si fa riferimento? Che ne dici di 'char [128] =" ";'? Solo inizializzando un buffer? Va tutto bene? O è 'char [128] = {'\ 0'};' meglio? – nus

+0

Secondo il libro di riferimento di Randal Albert, 'char c [4] =" foo ";' posiziona un carattere nullo per te e secondo il libro si consiglia di scriverlo come 'char [4] =" foo " ; '. 'char c [3] =" foo ";' è illegale perché abbiamo bisogno di riservare uno spazio per il carattere null terminante sul retro. – user3437460

+0

@user vale la pena leggere la mia intera risposta che dice "Gli array devono essere dichiarati un elemento più grande per contenere la stringa che termina '\ 0'." –

0

litb has the technically correct answer.

Per quanto riguarda un parere, dico solo vivi con lo "spreco" dell'extra "\ 0". Così tanti bug sono il risultato del codice che si aspetta un nullo che termina dove non lo è (questo consiglio può sembrare andare direttamente contro qualche altro consiglio che ho dato solo un giorno o due fa per non preoccuparmi di azzerare un intero buffer. contraddizione - Ho ancora sostenuto null terminando la stringa nel buffer).

Se non si riesce a convivere con il terminatore '\ 0' a causa di alcune semantiche nella struttura dei dati con cui si ha a che fare, come se fosse parte di una struttura più grande, è sempre possibile avviare l'array te (che credo dovrebbero essere meno efficiente di quello che il compilatore avrebbe potuto fare per voi):

#define MY_STRING_LITERAL "hello world" 

char stringLiteral[sizeof(MY_STRING_LITERAL) - 1]; 

memcpy(stringLiteral, MY_STRING_LITERAL, sizeof(stringLiteral)); 
+0

penso che il tuo metodo dovrebbe essere efficiente come quello del compilatore per gli array di char con classe di archiviazione automatica, ma per i char array con classe di archiviazione statica o quelli in ambito globale penso che non ci sia alcuna copia di run-time eseguita dal compilatore. – Pooria

+0

@ garrett2011: probabilmente è vero per gli elementi 'const char []', ma penso che il più delle volte gli array non-const abbiano i loro valori iniziali copiati dall'immagine del programma 'text' (che non è scrivibile sulla maggior parte delle piattaforme) in RAM prima che 'main()' sia invocato. Finché il 'memcpy()' viene fatto solo una volta, l'efficienza saggia equivale a sei, uno a una mezza dozzina dell'altro, indipendentemente dal fatto che sia eseguito dal runtime o dal codice. –

Problemi correlati