PDA

View Full Version : [C]puntatori a carattere e array di caratteri


mastoo
04-08-2007, 13:36
Non riesco a capire perche il programma 1 funziona, mentre il programma 2 va in "Segmentation fault"

Programma 1

#include <stdio.h>
#include <string.h>
/*reverse() inverte una stringa*/
void reverse(char *s);

main()
{
char s[] = "stringa di prova";

printf("%s\n",s);

printf("%s\n",(reverse(s),s));

}

void reverse(char *s)
{
char *p ;
char c ;
for(p = s + strlen(s)-1; s < p; s++,p--)
c = *s, *s = *p, *p = c;


}

programma 2

#include <stdio.h>
#include <string.h>
/*reverse() inverte una stringa*/
void reverse(char *s);

main()
{
char *s = "stringa di prova";

printf("%s\n",s);

printf("%s\n",(reverse(s),s));

}

void reverse(char *s)
{
char *p ;
char c ;
for(p = s + strlen(s)-1; s < p; s++,p--)
c = *s, *s = *p, *p = c;


}


in teoria sia s[] che *s dovrebbero puntare ad un area di memoria inizializzata... :mbe: o no?

uso il compilatore gcc 4.1.2

andbin
04-08-2007, 13:50
in teoria sia s[] che *s dovrebbero puntare ad un area di memoria inizializzata... :mbe: o no?Non sono esattamente la stessa cosa!!!

char s[] = " .... ";

istanzia un array di char sullo stack inizializzato in modo da contenere i caratteri della stringa literal.

char *s = " .... ";

istanzia un puntatore sullo stack in modo che punti direttamente ad una stringa literal.

Nel primo caso la stringa è sempre alterabile, in quanto "vive" in una zona di memoria alterabile (lo stack). Nel secondo caso stai andando a scrivere sopra una stringa "literal", che in base al sistema operativo/compilatore molto probabilmente è allocata in una sezione di memoria read-only. (e su Linux accade proprio questo).

Scrivere sopra una stringa literal non è una cosa da fare.


P.S. occhio a una sintassi come:
printf("%s\n",(reverse(s),s));

È chiaro cosa fa: prima valuta (esegue) la funzione reverse, poi valuta 's' che è poi il valore passato a printf.
La cosa più semplice è fare in modo che una funzione come reverse, ritorni un puntatore alla stringa, in modo da fare più semplicemente:

printf("%s\n", reverse(s));

mastoo
04-08-2007, 14:07
grazie andbin

scusa ancora una cosa

quindi

char *p = "prova";
*p = 's';
mi da segmentation fault perche p punta ad un area di memoria read-only
mentre

char s [] = "prova"
p = s;
*p = 's';
si puo fare perche p punta un area di memoria modificabile.
è l'unico modo per avere un puntatore ad un area di memoria gia inizializzata e modificabile?

andbin
04-08-2007, 14:21
char *p = "prova";
*p = 's';
mi da segmentation fault perche p punta ad un area di memoria read-onlySe è veramente readonly dipende dal sistema operativo e dal compilatore.
In Linux le stringhe costanti vengono per default allocate in una sezione readonly, a meno che tu ad esempio specifichi in fase di compilazione l'opzione -fwritable-strings, per cui le stringhe costanti vengono messe in un segmento di memoria writable e senza "unicizzarle".
Ma come dice anche il man di gcc ... scrivere su una stringa costante è una cattiva idea.


char s [] = "prova"
p = s;
*p = 's';
si puo fare perche p punta un area di memoria modificabile.
è l'unico modo per avere un puntatore ad un area di memoria gia inizializzata e modificabile?Tramite una inizializzazione fatta nella definizione della variabile, sì.