2011-09-25 15 views
8

Sto cercando di capire perché il seguente codice è illegale:cambiando un carattere in una stringa di c

int main() 
{ 
    char *c = "hello"; 
    c[3] = 'g'; // segmentation fault here 
    return 0; 
} 

Qual è il compilatore fa quando incontra char *c = "hello";?

Il modo in cui lo capisco, è un array automatico di caratteri e c è un puntatore al primo carattere. Se è così, c[3] è come *(c + 3) e dovrei essere in grado di effettuare l'assegnazione.

Solo cercando di capire come funziona il compilatore.

+2

** le matrici non sono puntatori ** e ** i puntatori non sono matrici **. La stringa letterale ('" ciao "') è una matrice di 6 caratteri (conta il terminatore null). Leggi la sezione 6 del [comp.lang.c faq] (http://c-faq.com/). Una volta fatto, leggi anche le altre sezioni :) – pmg

+4

Duplicato di troppi per elencare qui. –

+1

Abbiamo bisogno di introdurre un filtro nel SO question code di domanda che rileva 'char * XX =" ... "' e fornisce la risposta lì e poi, in linea nella finestra di dialogo domanda posta. –

risposta

7

c'è una differenza tra questi:

char c[] = "hello"; 

e

char *c = "hello"; 

Nel primo caso il compilatore alloca spazio sulla pila di 6 byte (cioè 5 byte per "ciao" e una per

Nel secondo caso il compilatore genera una stringa const statica chiamata "ciao" in un'area globale (ovvero una stringa letterale e alloca un puntatore sullo stack inizializzato in modo che punti a quella stringa const.

Non è possibile modificare una stringa const, ed è per questo che si ottiene un segfault.

+0

In C, un tipo di stringa letterale non è 'const char [N]' (con 'N' solo abbastanza grande). I letterali stringa hanno davvero tipo 'char [N]' ma cambiarli non è definito. – pmg

+0

@ pmg: I sta corretti –

+0

Non hai ricevuto una risposta corretta, perché non è una soluzione per la tua risposta. Vuole cambiare carattere specifico, nessuna modifica ad altra struttura, e sì è possibile :) – delive

8

Le costanti stringa sono immutabili. Non è possibile cambiarli, anche se li si assegna a un char * (quindi assegnarli a un const char * in modo da non dimenticare).

Per andare in qualche dettaglio, il codice è più o meno equivalente a:

int main() { 
    static const char ___internal_string[] = "hello"; 
    char *c = (char *)___internal_string; 
    c[3] = 'g'; 
    return 0; 
} 

Questo ___internal_string è spesso assegnato a un segmento di dati di sola lettura - qualsiasi tentativo di modificare i dati ne risulta in un incidente (in senso stretto, possono verificarsi anche altri risultati - questo è un esempio di "comportamento indefinito"). A causa di motivi storici, tuttavia, il compilatore consente di assegnare a un char *, dando la falsa impressione che è possibile modificarlo.

Nota che se avete fatto queste cose, che avrebbe funzionato:

char c[] = "hello"; 
c[3] = 'g'; // ok 

Questo perché stiamo inizializzazione di un array di caratteri non-const. Sebbene la sintassi sia simile, viene trattata in modo diverso dal compilatore.

+2

+1 per * approssimativamente * ... ma in C, un tipo letterale stringa non è 'const char [N]' (con 'N' abbastanza grande). I letterali stringa hanno davvero tipo 'char [N]' ma cambiarli non è definito. – pmg

+0

Ho detto _roughly_ equivalent :) – bdonlan

1

Non è possibile modificare il contenuto di una stringa letterale. Devi fare una copia.

#include <string.h> 

int main() 
{ 
    char *c = strdup("hello"); // Make a copy of "hello" 
    c[3] = 'g'; 
    free(c); 
    return 0; 
} 
+0

Vale la pena notare che l'uso di 'char c []' come suggerito dagli altri poster lo rende meno incline agli errori, dal momento che non è necessario liberare nulla. – Staven

Problemi correlati