Pagina 1 di 1

Puntatori e costanti

Inviato: mer 23 gen 2008, 21:07
da afterjames
Salve a tutti, ho un dubbio amletico sui puntatori in C.Ho sempre saputo che un buffer si può dichiarare indifferentemente come:

Codice: Seleziona tutto


char * const buffer1="blablabla";

oppure come un array :

Codice: Seleziona tutto


char buffer2[]="blablabla";

essendo un array equivalente ad un puntatore costante a dati variabili, cioè in cui non è possibile cambiare l'indirizzo a cui punta ma soltanto i valori "puntati".

Era tutto abbastanza chiaro, finchè un giorno non provai a fare :

Codice: Seleziona tutto

char *const s="bla bla";
char * ptr;
ptr = strtok(s," ");
Ottenendo un errore di segmentazione..Cosa che non accade se invece faccio:

Codice: Seleziona tutto

char  s[]="bla bla";
char * ptr;
ptr = strtok(s," ");
Che differenza c'è tra la versione con il puntatore e quella con il vettore?

Re: Puntatori e costanti

Inviato: mer 23 gen 2008, 23:11
da Calzo
Dovrebbe essere legato al fatto che definendo una stringa tra *s="" (o const *s="") viene allocata una zona di memoria read-only.
Infatti se fai:

Codice: Seleziona tutto

char s[]="abc";
char t[]="123";
char *x="def";
char *y="456";

void main() {
   printf("%X\n%X\n%X\n%X\n",s,t,x,y);
}
vedrai che la memoria non è contigua. A me x esempio torna questo:

Codice: Seleziona tutto

80495F0
80495F4
80484D4
80484D8
Inoltre la funzione che hai usato tu modifica direttamente *s. Ti dovrebbe dare un seg fault anche se fai s[1]='x'.

Re: Puntatori e costanti

Inviato: mer 23 gen 2008, 23:13
da phobos3576
Se apri un terminale e dai il comando man strtok puoi notare che:

Codice: Seleziona tutto

Avoid using these functions.  If you do use them, note that:

              These functions modify their first argument.

              These functions cannot be used on constant strings.

              The identity of the delimiting character is lost.

              The  strtok() function uses a static buffer while parsing, so it's
              not thread safe. Use strtok_r() if this matters to you.
Quindi, strtok modifica il suo primo argomento!

La stringa "bla bla", creata come hai fatto tu, è una stringa costante; il compilatore la sistema nel blocco dati globale del programma.
Come risulta dallo standard ANSI C: "se si tenta di modificare una stringa costante, il risultato è indefinito".
E' la stessa situazione che si verifica quando si scrive:

Codice: Seleziona tutto

printf("%s\n", "ciao");
La stringa "ciao", non avendo un nome, non risulta accessibile in scrittura.

Il modo corretto di procedere consiste nello scrivere, ad esempio:

Codice: Seleziona tutto

char mystr[] = "bla bla";
char *s = mystr;

Re: Puntatori e costanti

Inviato: gio 24 gen 2008, 10:17
da afterjames
Allora..Due cose:La stringa così dichiarata:

Codice: Seleziona tutto

char *const str="blablabla";

Non è costante, in quanto è il puntatore ad essere costante(e non i valori puntati!).Questa è una stringa costante:

Codice: Seleziona tutto


const char* strcost="blablabla";

Ora, utilizzando la strtok, anche con una semplice:

Codice: Seleziona tutto


char *str="bla blabla";
char *ptr;

ptr=strtok(ptr," ");
Ottengo ugualmente un errore di segmentazione..Ma dovrei aver capito perchè!In realtà c'è differenza tra il dichiarare una stringa come un buffer e come un puntatore.Su un manuale ho letto che:

"Alcuni compilatori potrebbero sistemare una variabile di tipo char* che sia stata inizializzata con una stringa letterale,
in una locazione di memoria in cui non possa essere modificata :-k "

Dovrebbe essere per questo il motivo..Grazie a tutti

Re: Puntatori e costanti

Inviato: gio 24 gen 2008, 10:58
da targzeta
afterjames ha scritto:Allora..Due cose:La stringa così dichiarata:

Codice: Seleziona tutto

char *const str="blablabla";

Non è costante, in quanto è il puntatore ad essere costante(e non i valori puntati!).
Errore, questa è una dichiarazione di puntatore costante a stringa che viene memorizzata in un area di memoria in read only, quindi, se vuoi è costante.

Con questa dichiarazione, anche fare

Codice: Seleziona tutto

str[0]='c';
non è valido.

Per usare una funzione che modifica l'area di memoria, devi o usare l'allocazione dinamica, oppure fare una dichiarazione del tipo:

Codice: Seleziona tutto

char str[]="blablabla";
in questo caso, str punterà ad una locazione di memoria che verrà allocata in fase di esecuzione e che conterrà la stringa "blablabla".
Nota che in questo caso, str è ancora un puntatore costante, nel senso che non è valido fare:

Codice: Seleziona tutto

str="pollo";
ma in questo caso è possibile modificare il contenuto di memoria a cui esso punta.

La tua dichiarazione invece è molto più restrittiva, il tuo puntatore str non può puntare a nient'altro che alla stringa "blablabla", e, l'area di memoria che contiene la stringa "blablabla" non può essere modificato. La tua dichiarazione è simile a questa:

Codice: Seleziona tutto

const char str[]="blablabla";
Spina

Re: Puntatori e costanti

Inviato: gio 24 gen 2008, 21:02
da robbybby
Io evito la strtok come la peste! Mi ha dato un sacco di problemi appena un programma in cui la usava e' passato da single thread a multi thread.
Preferisco fare il parsing usando la strchr(). Alla fine e' comoda uguale, ed esente da problemi in programmi multithreding (semplicemente perche' non c'e' il buffer statico, e i puntatori ai vari token me li tengo io su variabili automatiche, quindi sul mio stack).