2009-02-23 15 views
44

Sono un po 'sorpreso da quanto segue.Assegnazione di stringhe a matrici di caratteri

Esempio 1:

char s[100] = "abcd"; // declare and initialize - WORKS 

Esempio 2:

char s[100]; // declare 
s = "hello"; // initalize - DOESN'T WORK ('lvalue required' error) 

mi chiedo il motivo per cui il secondo approccio non funziona. Sembra naturale che dovrebbe (funziona con altri tipi di dati)? Qualcuno potrebbe spiegarmi la logica dietro a questo?

risposta

38

Quando si inizializza un array, C consente di riempire con valori. così

char s[100] = "abcd"; 

è fondamentalmente lo stesso come

int s[3] = { 1, 2, 3 }; 

ma non permette di fare l'assignmend poiché s è un array e non un puntatore libero. il significato di

s = "abcd" 

è quello di assegnare il valore del puntatore di "ABCD" a 's', ma non si può cambiare s da allora nulla punterà alla matrice.
Questo può funzionare e funziona se s è un char* - un puntatore che può puntare a qualsiasi cosa.

se si vuole copiare la stringa semplice utilizzo strcpy

+3

Buona risposta, tranne che non si dovrebbe mai usare strcpy semplice più a lungo. Usa strncpy o strlcpy. – dwc

+3

Inoltre, s dovrebbe essere const char *, non char *. – aib

+1

's [0] = 'x'; s [1] = 'y'; s [2] = 'z'; s [3] = 'm'; 'funziona se si desidera sostituire i caratteri della stringa uno per uno anche dopo l'inizializzazione. – RBT

9

Inizializzazione e assegnazione sono due operazioni distinte che si verificano utilizzando lo stesso operatore ("=") qui.

41

Non esiste una "stringa" in C. Le stringhe sono matrici di caratteri, terminata da NULL per convenzione. Poiché non è possibile assegnare gli array in C, non è possibile assegnare le stringhe. Lo zucchero letterale "ciao" è sintattico per const char x[] = {'h','e','l','l','o','\0'};

Il modo corretto sarebbe:

char s[100]; 
strncpy(s, "hello", 100); 

o meglio ancora:

#define STRMAX 100 
char s[STRMAX]; 
size_t len; 
len = strncpy(s, "hello", STRMAX); 
+0

Non l'approccio consigliato. Attenzione alle stranezze di strncpy: http://stackoverflow.com/a/1258577/2974922 – nucleon

3
1 char s[100]; 
2 s = "hello"; 

Nell'esempio che hai fornito, s è in realtà inizializzato alla linea 1, non la linea 2. Anche se non ha assegnato un valore in modo esplicito a questo punto, il compilatore ha fatto. Alla riga 2, si sta eseguendo un'operazione di assegnazione e non è possibile assegnare un array di caratteri a un altro array di caratteri come questo. Dovrai usare strcpy() o un qualche tipo di loop per assegnare ogni elemento dell'array.

2

Per ampliare il Sparr's answer

inizializzazione e assegnazione sono due operazioni distinte che capita di utilizzare lo stesso operatore ("=") qui.

Pensate a come questo:

Immaginate che ci sono 2 funzioni, chiamate InitializeObject e AssignObject.Quando il compilatore vede thing = value, esamina il contesto e chiama uno InitializeObject se stai creando un nuovo thing. Se non lo sei, chiama invece AssignObject.

Normalmente questo va bene come InitializeObject e AssignObject di solito si comportano allo stesso modo. Tranne quando si tratta di array di caratteri (e pochi altri casi limite), nel qual caso si comportano in modo diverso. Perché questo? Bene, questo è un intero altro post che coinvolge lo stack vs l'heap e così via e così via.

PS: Per inciso, pensando in questo modo sarà anche aiutare a capire costruttori di copia e altre cose del genere, se mai avventurarsi in C++

0

Si noti che si può ancora fare:

s[0] = 'h'; 
s[1] = 'e'; 
s[2] = 'l'; 
s[3] = 'l'; 
s[4] = 'o'; 
s[5] = '\0'; 
+0

È molto più bello e più facile da usare strncpy(), anche se sono abbastanza sicuro da strncpy() fa esattamente questo internamente. –

+0

Ovviamente. Ma questo è il più vicino possibile a s = "ciao"; " In realtà, questo dovrebbe essere stato implementato in C, visto come è possibile assegnare le strutture. – aib

+0

Voglio dire, la copia membro per compito nelle strutture ma non negli array non ha senso. – aib

-3

Quello che vorrei utilizzare è

char *s = "abcd"; 
+0

La maggior parte di noi non lo farebbe, perché rischia un comportamento indefinito. Quanto sopra è sicuro solo per 'const char *'. –

0

è possibile utilizzare questo:

yylval.sval=strdup("VHDL + Volcal trance..."); 

Dove yylval è char *. strdup di fa il lavoro.

+0

strdup da fa il lavoro :) – Yekatandilburg

Problemi correlati