Repository 32bit  Forum
Repository 64bit  Wiki

Puntatori e costanti

Forum dedicato alla programmazione.

Moderatore: Staff

Regole del forum
1) Citare in modo preciso il linguaggio di programmazione usato.
2) Se possibile portare un esempio del risultato atteso.
3) Leggere attentamente le risposte ricevute.
4) Scrivere i messaggi con il colore di default, evitare altri colori.
5) Scrivere in Italiano o in Inglese, se possibile grammaticalmente corretto, evitate stili di scrittura poco chiari, quindi nessuna abbreviazione tipo telegramma o scrittura stile SMS o CHAT.
6) Appena registrati è consigliato presentarsi nel forum dedicato.

La non osservanza delle regole porta a provvedimenti di vari tipo da parte dello staff, in particolare la non osservanza della regola 5 porta alla cancellazione del post e alla segnalazione dell'utente. In caso di recidività l'utente rischia il ban temporaneo.

Puntatori e costanti

Messaggioda afterjames » mer gen 23, 2008 21:07

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?
afterjames
Linux 1.0
Linux 1.0
 
Messaggi: 64
Iscritto il: lun gen 14, 2008 14:14

Re: Puntatori e costanti

Messaggioda Calzo » mer gen 23, 2008 23:11

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'.
Ultima modifica di Calzo il mer gen 23, 2008 23:20, modificato 1 volta in totale.
Avatar utente
Calzo
Linux 2.0
Linux 2.0
 
Messaggi: 112
Iscritto il: sab ott 06, 2007 21:21
Località: MN
Slackware: 10.2 | 13
Desktop: Fluxbox | KDE

Re: Puntatori e costanti

Messaggioda phobos3576 » mer gen 23, 2008 23:13

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;
Avatar utente
phobos3576
Staff
Staff
 
Messaggi: 2980
Iscritto il: sab apr 16, 2005 23:00
Slackware: 13.1
Kernel: 2.6.37-smp
Desktop: KDE 4.5.3

Re: Puntatori e costanti

Messaggioda afterjames » gio gen 24, 2008 10:17

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
afterjames
Linux 1.0
Linux 1.0
 
Messaggi: 64
Iscritto il: lun gen 14, 2008 14:14

Re: Puntatori e costanti

Messaggioda targzeta » gio gen 24, 2008 10:58

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
Linux Registered User #454438
Se pensi di essere troppo piccolo per fare la differenza, prova a dormire con una zanzara -- Dalai Lama
20/04/2013 - Io volevo Rodotà
Avatar utente
targzeta
Iper Master
Iper Master
 
Messaggi: 6169
Iscritto il: gio nov 03, 2005 14:05
Località: Carpignano Sal. (LE) <-> Pisa
Nome Cognome: Emanuele Tomasi
Slackware: current
Kernel: latest stable
Desktop: IceWM

Re: Puntatori e costanti

Messaggioda robbybby » gio gen 24, 2008 21:02

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).
Avatar utente
robbybby
Linux 3.x
Linux 3.x
 
Messaggi: 1175
Iscritto il: sab dic 16, 2006 10:48
Località: Fra Trantor e Terminus
Slackware: 13.1 / 64 bit
Kernel: 3.3.x
Desktop: KDE 4.4.5


Torna a Programmazione

Chi c’è in linea

Visitano il forum: Nessuno e 1 ospite