Newsgroup: it.comp.lang.c++
Titolo: Null character in string... ^_^

 			  << "Terzo elemento: " << str[2] << endl;
non fa quel che mi aspetto?
Mi sarei aspettato l'eliminazione di '\0', cosicché la stringa sarebbe
diventata "std" + "[...]" ( memoria sporca fino a un '\0' casuale ).
Pero' noto che quel "str[2]" me lo stampa correttamente! wow! ^_^
( cosa ho sovrascritto? la variabile "futile" oppure il codice asm di
"str[2] = 'd'" ? )
( da quanto ho visto, nessuna delle due. ma allora cosa? com'e'
memorizzata una variabile string? essendo una classe dovrebbe
memorizzare un bel po' di roba, no? )
Forse perché le string *non* hanno il null finale?
Solo "str.c_str()" ce l'ha, quindi?
( mi sto rispondendo da solo alle domande? che posto a fare? ^_- )
Credo proprio che io abbia bisogno di un buon manuale dedicato alla
standard library... ^_-
Inizio da 
http://cpp.programmazione.it
 ? ^_^
10x,
The Student

 Pero' noto che quel "str[2]" me lo stampa correttamente! wow! ^_^
Che e' proprio quello che avviene.
Maurus

 giustamente il carattere 'd' appena assegnato:
Uh? Scusa, ma così sembra che tu gli voglia "spiegare" perché succede
qualcosa che in realtà a lui non succede.
Guarda, tirare ballo il carattere '\0' quando si parla di std::string è
inutile e fuorviante, anche perchè un std::string può contenere diversi
caratteri '\0' (così come qualsiasi altro carattere).
std::string è una classe provvista di un operator[]. Se l'argomento che
viene passato è uguale o superiore a size() il comportamento è indefinito.
Quello che succede dipende dall'implementazione o da fattori casuali, ma
mi aspetto che con l'implementazione tipica usare un indice pari a size()
non abbia effetti disastrosi in quanto il buffer interno sarà di almeno un
1 carattere più lungo di size() (in questo modo c_str() non deve
riallocare e copiare). La quantità di caratteri da stampare viene
determinata con il metodo size(); la presenza o l'assenza di un '\0' è
ininfluente.
Max

 wrote in message
news:Pine.LNX.4.21.0301090306270.18773-100000@blomma...

Allora  vuol dire che l'implementazione delle string e dell'operator [], nel
VisualC++ mi da' casualmente un risultato che io mi sarei aspettato
logicamente.
In quanto l'output del programma di esempio gia' visto mi dava:
Stringa: std-----------------------------²²²²¦¦¦Q
Terzo elemento: d
E l'interpretazione logica che ne ho ricavato e' che std[2] = 'd' ha fatto
si' che l'operator [] andasse a scrivere il carattere susseguente al buffer
"st" della string str e susseguentemente la cout di str stampa una serie
casuale di caratteri dopo std (-----------------------------²²²²¦¦¦Q).
E li' io ho interpretato che stampasse fino ad incontrare il primo carattere
'/0', altrimenti non capisco quale e' il motivo che ne ferma la stampa.
A meno che la scrittura di 'd', oltre la size(), non dia un comportamento
indefinito e ne cambia la size() stessa in modo casuale.
E' strano comunque che se scrivo altri caratteri al posto della 'd',
l'output seguente il carattere, rimane sempre lo stesso.
Maurus

 Inizio da 
http://cpp.programmazione.it
 ? ^_^
Purtroppo hai postato *dopo* Natale. Era una buona occasione per farti
regalare "The C++ Standard Library", di Nicolai Josuttis, Addison
Wesley. Se hai ricevuto un po' di soldini, e' un buon investimento.
 
Ciao,
Nicola

 la stampa.
Può darsi che nella SL che usi tu operator<< sia implementato con una
chiamata a c_str(), che in questo caso probabilmente restituirà un buffer
non più (causa nostra operazione illegale) adeguatamente terminato. (Solo
una congettura, ovviamente.)
Con VC++7, invece, accade quello che ha riscontrato l'OP.
Se vuoi approfondire la faccenda, puoi fare una prova inserendo uno '\0'
in una posizione "legale" qualsiasi e vedere cosa stampa. Oppure vai a
guardarti l'implementazione.
In generale non sono d'accordo che sia "logico" aspettarsi che l'output di
un std::string si interrompa al primo '\0'. Gli std::string possono
contentenere dati binari arbitrari.
Max

Mi immetto nella discussione per fare una domanda: mi spiegate che differenza c'e` tra c_str() e
data() ? Entrambe ritornano un puntatore costante all'array di char che rappresenta la stringa, ma
c_str() aggiunge uno '\0' terminatore... ma allora per quale motivo se faccio una printf su entrambi
i metodi ottengo sempre lo stesso risultato?
In sostanza: a cosa cavolo serve fare due funzioni sostanzialmente uguali?
Ciao,
Cecco
PS: Ho dato un occhiata all'implementazione (VC++ 6): in pratica quando si crea una string, in base
alla lunghezza della stringa di inizializzazione viene allocata una certa quantita` di memoria, poi
copiata la stringa e infine viene copiato von memcpy un valore diverso da 0 sui byte rimanenti.

 una printf su entrambi i metodi ottengo sempre lo stesso risultato?
Il fatto che tu ottenga lo stesso risultato non è rilevante. 
data() restituisce un puntatore a una array di caratteri lungo almeno
quanto size(). c_str() restituisce un puntatore ad un array di caratteri
sicuramente terminato con uno '\0'. Quest'ultima garanzia non esiste con
data(). Usare data() con funzioni che si aspettano un puntatore a una
stringa null-terminated non garantisce un comportamento definito.
Max

 Nicola
Ciao e grazie di tutto,
The Student

 Maurus
Grazie comunque,
The Student

 size() (in questo modo c_str() non deve riallocare e copiare)
Cioe'? Quando si richiama il metodo c_str() non viene comunque creata
una copia della stringa da un'altra parte?
Sarebbe anche logico quel che dici, ma poi modificherebbe la stringa
d'origine, no? Ma credo basti che c_str() si assicuri che a str[size] ci
sia '\0'.
Non mi e' chiara una cosa: una variabile string in memoria come e'
fatta? C'e' anche la sua dimensione oppure e' tutto come ai "bei" tempi
del C ? ^_^
Grazie,
The Student

 str[5] ==> *(str + 5)
che potrebbe fare anche il compilatore nella prima passata (un po' come
le costanti, no? sempre eccetto per le classi che lo ridefiniscono)
Ho fatto abbastanza confusione?
Nicolai Josuttis, sto arrivando! ^_-
Au revoir,
The Student
ps. scusate per aver monopolizzato il ng! :D

 Cioe', a me piacerebbe sapere se una string finisca o meno con il '\0'.
L'ho già scritto, ripeto: lo Standard non richiede che ci sia un '\0' in
fondo alla stringa. (Per usare un std::string con funzioni che si
aspettano puntatori ad array null-terminated, bisogna usare c_str(), che
restituisce un buffer terminato con '\0'.)
Max

 Posso andare a vederlo tra i sorgenti? Puo' cambiare tra compilatori?
Va be' che vieni dall'assembler, ma possibile che nessuno ti abbia mai
parlato di incapsulamento? ;-)
Ciao,
Nicola

 C ? ^_^
size() deve avere complessita` costante, e non puo` permettersi di
contare i caratteri ogni volta.  Bisogna quindi memorizzare la
dimensione o qualcosa che permetta di calcolarla rapidamente
(es. puntatore inizio e fine).
        Mauro

 stringa null-terminated non garantisce un comportamento definito.
Ma se c_str(), come suppongo, e` stata inserita per garantire compatibilita' con funzioni in stile C
che si aspettano array di char null terminated, per quale motivo e` stata inserita anche data() ?
Che utilíta` puo` avere?
Ciao,
Cecco

Solo un grazie mille a chi m'ha risposto in questo thread.
A giorni ordinero' il libro di Josuttis sulla STL.
Grazie di tutto,
The Student

 possibile scrivere sul code segment?
Probabilemente è più sensato cercare di fare queste cose con
linguaggi di script, come python (o ruby).
Prova a chiedere su it.comp.lang
ciao
--
Gerolamo

 quelle locazioni? <io> Chiedo in ng piu' appropriati? <voi> siii'!
ma no, ti rispondo io. Loro sono brutti e cattivi, ma io sono brava. Ti 
do' anche questa caramellina, poi. Devi semplicemente dire al linker di 
rendere il segmento .text (quella parte dell'eseguibile che contiene il 
codice) scrivibile, se non lo è già. Ecco quelli che conosco:
Microsoft Incremental Linker: link -section:.text,ERW
Borland Turbo Incremental Linker: ilink32 -GS:.text=ERW
GNU ld: non so se si possa. In ld --help non vedo niente di pertinente
-- 
 < 
http://www.reactos.com/
 >  Open source clone of Windows NT. Current
     Don't stand, REACT!      version 0.0.21. C, C++ and ASM developers
                              and beta testers are welcome!