Newsgroup: it.comp.programmare.win32
Titolo: Problema con puntatori

Sto veramente andando fuori di testa
non mi funziona una cosa di questo tipo
void Cambia (char * C1,char* C2){
    strcpy (C1,"AAA");
    strcpy (C2,"BBB");
}
[...]
char *E="XXX";
char *N="YYY";
Cambia (E, N);
cout << N << " - " <<  E  << endl;
[...]
Sto in VC++, provo a vedere che succede con il debug e quando
chiamo la funzione strcpy mi da un "access violation".
Dov'è che sbaglio?
Ciao

 wrote in message
a8rs1n$4l9$1...@newsreader.mailgate.org...

Non hai allocato il puntatore!!! Ossia scrivere char *E = "XXX"; dice
al compilatore di prepare un puntatore a caratteri chiamato E che poi
segue la stringa XXX (ecco perchè tu ci vedi la stringa XXX nel debug,
ma in realtà non è allocato!)
Devi scrivere :
    char E[3] = "XXX";
    char N[3]= "YYY";
così ai un puntatore E che punta ad una stringa allocata di 3 caratteri.
oppure :
        char E[] = "XXX";
        char N[] = "YYY";
così il compilatore si conta quanti caratteri è lunga la stringa.
Oppure, se vuoi usare i puntatori per inserire stringa di lunghezza ignota
fai  :
    char *E;
    char *N;
    e poi , quando successivamente assegni le stringhe.
    E = malloc( numero di caratteri opportuno );
    N = malloc( numero di caratteri opportuno );
Ciao.

Bene,
Grazie 1000!

Dov'è che sbaglio?
La memoria puntata da E e N non e' necessariamente
modificabile, e' questo il motivo dell'access violation.
Al posto di un puntatore, puoi utilizzare un array.
-- 
Andrea Laforgia (
walkie...@libero.it
)
"Usenet is a strange place" [Dennis Ritchie]

così il compilatore si conta quanti caratteri è lunga la stringa.
Vedi sopra.
Lo fa comunque.


 No, e' la stessa cosa.
Questo non è vero. Infatti scritto così funziona e nell'altro caso c'è
errore.
Quindi non è la stessa cosa. Diciamo allora che scrivere così alloca
memoria modificabile mentre nell'altro caso no (cmq su questo punto
sarei proprio curioso di sapere come il compilatore espande
le due situazioni... per esempio se uso il gcc anzichè il Visual C++
o il Borland è la stessa cosa?).
Ciao e dibattiamone

memoria modificabile mentre nell'altro caso no 
Si e no, nel primo caso *non e' detto* che sia modificabile.
E' molto diverso.  L'allocazione fatta da te e' quella di un
vettore e gli elementi di un vettore, se non dichiarati
costanti, sono per loro natura modificabili.


costanti, sono per loro natura modificabili.
Mentre nel secondo caso invece mi viene preparato un vettore (ovvio).
Però questo discorso sulla modificabilità continua a lasciarmi
perplesso... nel senso che: non è che è non modificabile (quando lo è)
perchè non allocata? Ossia non è da considerarsi alla stessa stregua
di memoria alloca e poi lockata bensì è memoria utilizzata
ed abbandonata a sè stessa, per fare un esempio in programamzione
concorrente si potrebbe anche andare a rifinirci sopra modificando
il contenuto "XXX"? Fammi capire!
Ciao

il contenuto "XXX"? Fammi capire!
Che vuoi dire con "memoria utilizzata e abbandonata a se
stessa" ?  A mio avviso ti stai perdendo in un bicchiere
d'acqua.  Se il contenuto di XXX e' conservato in un'area di
memoria protetta (plausibile, visto che e' un dato
costante), allora il tentativo di accesso solleva
un'eccezione.



[cut]
OK! Adesso credo di aver capito...
Cmq, per "memoria utilizzata ed abbondonata a sè stessa"
intendevo dire qualcosa del tipo:
char *pino;
pino = malloc( 8 );
memset( pino, 0, 16 );
Questa microprogramma azzera 16 byte successivi all'indirizzo puntato da
pino,
pure se dopo 8 byte non hai riservato memoria (e sotto Windows98 garantisco
che non genera errore di nessun tipo, sotto Linux, ovviamente, avrei
un "segmentation fault" e sotto Windows 2000 un messaggio di avvertimento).
Con un errore di tal tipo, per esempio può accadere che vai ad
azzerare il contenuto di altre variabili... volevo capire se il puntatore
scritto in
quel modo non è l'equivalente di questo errore, ossia dell'azzeramento
oltre gli 8 byte allocati ma come tu hai spiegato lo spazio
di memoria per "XXX" viene riservato dal compilatore correttamente (anche
se in certi casi può essere costante e quindi non modificabile).
OK! Adesso mi torna. Scusa la menata. :-)
Ciao e thanx

un "segmentation fault" e sotto Windows 2000 un messaggio di avvertimento).
Non puoi assolutamente stabilire a priori quale sia il
comportamento di quel codice, sotto un particolare sistema
operativo.  Per lo standard, le tue istruzioni hanno un
"undefined behavior", il che vuol dire che e' plausibile
accada qualsiasi cosa.  Non puoi dire: sotto Windows98 e'
sicuro che non generi alcun errore, sotto Linux si', sotto
W2000 un semplice avvertimento.  Potresti avere un seg fault
sotto tutti e tre, come potresti non averlo, come potresti
averlo solo sotto alcuni, ecc... ecc...


 averlo solo sotto alcuni, ecc... ecc...
Vedi sopra.
Ciao

č sufficiente provare e vedere (ed č anche utile).
Non ci siamo: comportamento indefinito vuol dire che puo'
succedere qualsiasi cosa e non e' affatto detto che la
reazione del codice sia sempre la stessa.  Tieni anche
presente che non e' tanto "utile", quanto "pericoloso".
Immagina di andar a sovrascrivere, pur non avendo
access-violation, la zona di memoria occupata da un flag
utilizzato nel tuo codice, per stabilire se formattare o
meno il disco, senza chiedere conferma.  Per lo standard,
ribadisco, comportamento indefinito vuol dire "puo'
succedere qualsiasi cosa", ci puo' essere access-violation,
come puo' non esserci, ti si puo' formattare il disco, come
non ti si puo' formattare, e via dicendo, quindi il discorso
"provo e vedo cosa succede", non va bene.


 "provo e vedo cosa succede", non va bene.
Mi torna che sia pericoloso se il compilatore si comporta davvero
in modo indefinito (indipendentemente da quello che dice lo standard).
Tuttavia, visto che ti vedo così sicuro su questo cosa
mi voglio consultare con un mio amico che,
per lavoro, ha anche realizzato vari compilatori
e voglio chiedergli per curiosità come viene implementata
la parte che gestisce quel tipo di codice per vedere se
il comportamento è effettivamente casuale o cmq, dipendente dal codice
oppure in base al compilatore si possono avere delle reazioni note.
Effettivamente sapere questa cosa ha delle implicazioni
molto più importanti di quanto non possa sembrare....
Ciao
(P.S: ma come fai a ricordarti così bene lo standard? 8-) )

oppure in base al compilatore si possono avere delle reazioni note.
Non c'entra nulla il compilatore.


 Non c'entra nulla il compilatore.
Ho un pò guardato su Internet ed ho trovato questo che riassume il nostro
thread :
4.4: People keep saying the behavior is undefined, but I just tried it on an
       ANSI-conforming compiler, and got the results I expected.
A compiler may do anything it likes when faced with undefined behavior (and,
within limits,
with implementation-defined and unspecified behavior), including doing what
you expect.
It's unwise to depend on it, though.
E poi ancora...
The behavior of code which contains multiple, ambiguous side effects has
always been undefined (see question 5.23).  Don't even try to find out how
your compiler implements such things (contrary to the ill-advised exercises
in many C textbooks); as K&R wisely point out, "if you don't know how they
are done on various machines, that innocence may help to protect you."
Questi sono peggio di me  :-)  :
4.3: I've experimented with the code
              int i = 2;
              i = i++;
on several compilers.  Some gave i the value 2, some gave 3, but one gave 4.
I know the behavior is undefined, but how could it give 4?
Risposta : Undefined behavior means anything can happen.  (come mi hai detto
tu).
Grazie per avermi tolto questo dente (malato) e scusa ancora per il
mega-thread.
Ciao ciao