Newsgroup: it.comp.lang.c++
Titolo: Problema conversione da int a unsigned char e viceversa

Ciao a tutti ho il seguente problema :
Ho la necessità di comprimere utilizzando la zLib un buffer di int (con
segno).
La funzione compress (della zLib) accetta come buffer sorgente degli
unsigned char e chiaramente la sua inversa (uncompress) mi restituisce
sempre un buf. di unsigned char.
Come posso fare a trasformare quest'ultimo in int senza perdermi il segno ?
Grazie
Ciao Simo

Basta che alla zlip dai in pasto il pt giusto.
Supponiamo che il tuo array di int sia una cosa del tipo
int  *intArray;
A questo punto se vuoi un pt unsigned char che punti al tuo array basta che 
fai un cast:
unsigned char *uchar;
uchar = (unsigned char *)intArray;
e poi lo dai in pasto a Zlip.
Non ti preoccupare per i segni, alla fine della fiera un int e' pur sempre 
4 byte uno dietro l'altro per cui la compressione non tiene conto di segni 
e mica segni ma lavora sui byte.
Ovviamente il discorso vale anche per il processo inverso di 
decompresisone.

 e mica segni ma lavora sui byte.
e la dimensione sarà ovviamente in unsigned char cioè in byte e non in
int... quindi da qualche parte ci vorrà un sizeof come nella malloc.
Ciao
Antonio

 uchar = (unsigned char *)intArray;
mmm... siamo sicuri che questo sia legale E sia garantito il corretto
funzionamento?
Non riesco a trovare un riferimento preciso, ma queste conversioni
di tipo tramite puntatore mi lasciano piů di un dubbio.
-- 
Gerolamo

 wrote in news:bk45q8$ocg6b$1@ID-
202547.news.uni-berlin.de
:

Se pensi a come sono messi in memoria gli array, ti rendi conto che i 
tuoi dubbi sono vani.
La memoria per sua natura e' sequenziale, una sequenza di bit, meglio se 
parliamo di sequenza di byte.
Supponiamo che l'array di interi sia composto da 20 interi, per un totale 
di 20*sizeof(int) BYTE...dichiamo 20*4=80 byte
Supponiamo che l'array sia in memoria a partire dall'indirizzo fisico 
0x12345678
Se tu "punti" un puntatore a quell'indirizzo e leggi la sequenza di 80 
byte che rappresentano i 20 interi, che problema c'e'?

 byte che rappresentano i 20 interi, che problema c'e'?
Ok. Possiamo allora dire che a quel punto ti trovi con un
unsigned char[80]
con dentro il contenuto della tua memoria, giusto?
E adesso come torni agli "int"?
-- 
Gerolamo

 
non e' esattamente cosi'...non e' che hai allocato fisicamente un nuovo 
array di 80 char...hai semplicemente usato un puntatore per puntare a 
quella zona di memoria.
Per "rivedere" la memoria in formato int, basta puntare nuovamente in 
quel posto ma usando un puntatore di tipo int.
Il tipo del puntatore ti dice in che modo vuoi vedere quella zona di 
memoria...se la vuoi vedere come char usi un pt a char, se la vuoi vedere 
come int usi un pt a int, se la vuoi vedere come struct LaMiaStruct, usi 
un pt di tipo *LaMiaStruct e via dicendo.
int  arraydibase[20];
char *pChar;
int  *pInt;
// "punto" pChar all'array
pChar = (char*)arrayDiBase;
// supponendo che pChar punti all'array di base, "punto" pInt allo stesso
// array
pInt = (int*)pChar;

 LaMiaStruct, usi un pt di tipo *LaMiaStruct e via dicendo.
Non sono molto d'accordo, tant'è che il codice:
int * pi;
double d;
pi = &d;
deve dare un errore.
Quindi la mia domande sono:
1-
Cosa garantisce lo standard riguardo agli elementi a cui accedo
tramite un puntatore di tipo diverso da quello originale?
2-
Usando un cast stile C è compilabile il codice:
===
int * pi;
unsigned char * pc = (unsigned char *)pi;
===
Ma cosa succede esattamente alla conversione
int* => unsigned char* ?
E che significato hanno gli elementi a cui accedo quando
dereferenzio l'unsigned char * ottenuto?
3-
Ammesso di avere ottenuto un unsigned char * valido e
usabile, come posso tornare, partendo da esso, agli interi
da cui sono partito, avendo garantito che il significato
iniziale sia rimasto invariato?
-- 
Gerolamo

 byte che rappresentano i 20 interi, che problema c'e'?
In questa direzione probabilmente nessuno, anche se non e' affatto
garantito. Nella direzione contraria, ovvero assegnando tramite cast
un puntatore a char ad un puntatore ad intero non e' detto che
funzioni per problemi di allineamento.
Il doppio passaggio e' invece garantito se l'area puntata e' allocata
dinamicamente.
Ciao,
Nicola

 
Rifai il cast al contrario.
Ripeto che il puntatore non e' l'array...il puntatore punta ad un
indirizzo in memoria. La variabile di tipo puntatore occupa fisicamente
4 byte indipendentemente dal tipo di puntatore che usi e dalla
dimensione dell'array che punta. sizeof(p) dove p e' definito come char
*p ritorna 4 byte sizeof(p) dove p e' definito come int *p ritorna
sempre 4 byte 

 
Non ho capito nemmeno questa. Per doppio passaggio cosa intendi ?

 Non ho capito nemmeno questa. Per doppio passaggio cosa intendi ?
Lo standard garantisce che il puntatore restituito da new sia allocato
in modo adeguato a tutti i tipi di dimensione inferiore o uguale
all'area allocata.
Ciao,
Nicola

 
Mentre invece se alloco staticamente questo non e' garantito? 
Buono a sapersi 
In ogni caso, se parliamo di windows/linux quel che ho detto funziona; se 
passiamo ad altre architetture non mi pronuncio xche' non ne so nulla per 
cui mi fido di quello che dici
Ciao

 come int o come char.
immagino che tu stia parlando di x86, ma questo non e` il caso piu`
generale. Lo standard non garantisce affatto quel che dici tu: ci sono
delle archietetture sulle quali non e` fisicamente possibile mettere, ad
esempio, un interno su indirizzi non allineati.
ciao Anto
-- 
"Computer science is not about computers any more than astronomy
is about telescopes." -- EW Dijkstra