Repository 32bit  Forum
Repository 64bit  Wiki

Puntatori e costanti

Forum dedicato alla programmazione.

Moderatore: Staff

Regole del forum
1) Citare sempre la versione di Slackware usata e la versione del Kernel. Questi dati aiutano le persone che possono rispondere.
2) Specificare sempre il tipo di shell (bash, sh, csh, etc...)
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 dell'ultima regola 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 22: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 15:14

Re: Puntatori e costanti

Messaggioda Calzo » gio gen 24, 2008 0: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 gio gen 24, 2008 0:20, modificato 1 volta in totale.
Avatar utente
Calzo
Linux 2.0
Linux 2.0
 
Messaggi: 112
Iscritto il: sab ott 06, 2007 22:21
Località: MN
Slackware: 10.2 | 13
Desktop: Fluxbox | KDE

Re: Puntatori e costanti

Messaggioda phobos3576 » gio gen 24, 2008 0: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: dom apr 17, 2005 0:00
Slackware: 13.1
Kernel: 2.6.37-smp
Desktop: KDE 4.5.3

Re: Puntatori e costanti

Messaggioda afterjames » gio gen 24, 2008 11: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 15:14

Re: Puntatori e costanti

Messaggioda targzeta » gio gen 24, 2008 11: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
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: 5914
Iscritto il: gio nov 03, 2005 15: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 22: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: 1077
Iscritto il: sab dic 16, 2006 11: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 0 ospiti