View Full Version : [C]mettere int in vettore unsigned char come hex
sto scrivendo una applicazione client-server.
le comunicazioni tra i due avvengono inviando "messaggi" composti da un vettore di unsigned char che vengono tutti interpretati o come serie di caratteri ( se vine inviato/ricevuto una stringa) oppure come dei valori interi,ma
ho questo problema :
-----------------
int intero=3106;
unsigned char caratteri[20];
caratteri[5]=intero;
-----------------
che come capite NON funziona,perche'
(dec)3106 = (hex)C22
e ovviamente C22 NON ci sta in un solo unsigned char
dovrei fare :
caratteri[5]=0x0C
caratteri[6]=0x22
inoltre dato che devo inviare questi dati via tcp mi vedo costretto a doverli invertirli quindi :
caratteri[5]=0x22
caratteri[6]=0x0C
avete suggerimenti per risolvere questo problema ?
fantoibed
27-12-2004, 17:09
Originariamente inviato da honny
avete suggerimenti per risolvere questo problema ? Usare un vettore di unsigned int ? ;)
forse sto facendo un macello e non sono stato molto chiaro .
dunque ho un vettore di unsigned char :
unsigned char messaggio[20];
questo vettore lo "riempio" per esempio con dei caratteri:
messaggio[0]='c';
messaggio[1]='i';
messaggio[2]='a';
messaggio[3]='o';
oppure con dei valori in esadecimale (hex):
messaggio[4]=0x01;
messaggio[5]=0x02;
messaggio[6]=0xAA;
ora vorrei mettere in messaggio[7] il valore intero in base 10 3106 :
int intero = 3106;//OK
messaggio[7]=intero; //QUESTA COSA NON FUNZIONA !!!
ed e' giusto che non funzioni, perche' il valore massimo che posso mettere in un unsigned char e' 0xFF , cioe' 255 .
3106 in esadecimale e' : C22
in pratica devo utilizzare sia messaggio[7] sia messaggio[8],cioe':
messaggio[7]=0x0C;
messaggio[8]=0x22;
/\/\@®¢Ø
28-12-2004, 14:09
Originariamente inviato da honny
ora vorrei mettere in messaggio[7] il valore intero in base 10 3106 :
int intero = 3106;//OK
messaggio[7]=intero; //QUESTA COSA NON FUNZIONA !!!
ed e' giusto che non funzioni, perche' il valore massimo che posso mettere in un unsigned char e' 0xFF , cioe' 255 .
3106 in esadecimale e' : C22
in pratica devo utilizzare sia messaggio[7] sia messaggio[8],cioe':
messaggio[7]=0x0C;
messaggio[8]=0x22;
In realta' il numero di caratteri necessari possono essere ben piu' di due (tipicamente 4 in una generica macchina a 32 bit).
La cosa piu' semplice e' fare un cast dell'array ad un array di interi e poi scriverci direttamente. Se pero' devi mandare il messaggio su architetture differenti, ti conviene convertire il valore in un formato neutrale, e fissare il numero di bit che vuoi usare
Ad esempio, se ti bastano gli interi senza segno puoi fare qualcosa del genere (notazione C++, per il C ci potrebbero essere delle differenze minori):
#include <netinet/in.h>
...
uint32_t* x = (uint32_t*) messaggio;
x[0]=htonl(3106); // questo va a scrivere da messaggio[0] a messaggio[3]
Quando devi rileggere il valore dall'array fai la stessa cosa, convertendo pero' l'intero da "formato network" a quello specifico della macchina in uso:
#include <netinet/in.h>
...
uint32_t* x = (uint32_t*) messaggio;
uint32_t n = ntohl( x[0] );
Se non ti servono tutti e 32 i bit, ma te ne bastano 16, allora puoi usare uint16_t, htons e ntohs.
DISCLAIMER: codice non testato, pensato per un S.O. che potrebbe non essere il tuo, in ogni caso prima di provarlo fai un backup :p:D
fantoibed
28-12-2004, 17:53
Originariamente inviato da honny
unsigned char messaggio[20];
ora vorrei mettere in messaggio[7] il valore intero in base 10 3106
Un unsigned char è grande 1 byte, un integer è grande 2 bytes.
Devi modificare il tuo programma e dichiarare messaggio[20] come vettore di unsigned int e non di unsigned char.
Un unsigned char può variare da 0 a 255. Se vuoi un valore superiore devi orientarti su altri tipi di dato.... ;-)
Originariamente inviato da fantoibed
Un unsigned char è grande 1 byte, un integer è grande 2 bytes.
Devi modificare il tuo programma e dichiarare messaggio[20] come vettore di unsigned int e non di unsigned char.
Un unsigned char può variare da 0 a 255.
infatti e' quello che ho scritto io sopra .....
PS: il tipo di dati non lo posso cambiare se no lo avrei gia' fatto, mannaggia la miseriaccia LOL !!!
PS2:cmq ora provo a smazzare il cast come indicato sopra.
grazie gente.
/\/\@®¢Ø
28-12-2004, 18:29
Originariamente inviato da fantoibed
Un unsigned char è grande 1 byte, un integer è grande 2 bytes.
Non e' detto. Su macchine "comuni" un char nel 99% dei casi occupa 1 byte, ma non e' una regola scritta in nessuno standard (sono esistite macchine con chars da 12 bit e mi sembra pure da 11 :eek: :D ).
Su una macchina a 32 bit un intero e' solitamente di 32 bit, quindi 4 byte, era di 2 byte nelle architetture a 16 bit (o su macchine a 32 bit che eseguono codice a 16 bit )
fantoibed
28-12-2004, 18:38
Originariamente inviato da /\/\@®¢Ø
Non e' detto. Su macchine "comuni" un char nel 99% dei casi occupa 1 byte, ma non e' una regola scritta in nessuno standard (sono esistite macchine con chars da 12 bit e mi sembra pure da 11 :eek: :D ).
Su una macchina a 32 bit un intero e' solitamente di 32 bit, quindi 4 byte, era di 2 byte nelle architetture a 16 bit (o su macchine a 32 bit che eseguono codice a 16 bit )
Stai facendo un casino incredibile. Stiamo parlando di linguaggio C e non di architetture. I tipi di dati sono definiti dagli standard:
* char -128 to +127 8bit
* unsigned char 0 to +255 8bit
* short -32768 to +32767 16bit
* unsigned short 0 to +65535 16bit
* long -2 147 483 648 to +2 147 483 647 32bit
* unsigned long 0 to +4 294 967 295 32bit
* int -32768 to +32767 16bit
or
* int -2 147 483 648 to +2 147 483 647 32bit
* unsigned int 0 to +65535 16bit
or
* unsigned int 0 to +4 294 967 295 32bit
* float ??? 32bit
* double ??? 64bit
* long double ??? 80bit
or
* long double ??? 64bit
Che tu compili un programma per farlo girare su un pentium, su un PIC16F86 su un ATMEL, su un ARM, su un Itanium o su un TI sono comunque cazzi del compilatore quelli di utilizzare i registri che quel dato processare ha per poter memorizzare certi tipi di dato, ma i tipi di dato sono questi.
Li trovi su qualsiasi libro di C!!!
Probabilmente fai casino con l'architettura dei processori, ma il linguaggio C è tutt'altra cosa.
fantoibed
28-12-2004, 18:47
Originariamente inviato da honny
infatti e' quello che ho scritto io sopra .....
PS: il tipo di dati non lo posso cambiare se no lo avrei gia' fatto, mannaggia la miseriaccia LOL !!!
PS2:cmq ora provo a smazzare il cast come indicato sopra.
Viene un casino, però. Se in un array metti alcuni char e alcuni int come fai poi a sapere se vanno letti singolarmente o a coppie?
Che genere di programma stai scrivendo? Se posti un po' di codice in più provo a vedere cosa riesco a farci... ;)
end.is.forever
28-12-2004, 19:18
Non so cosa ci devi poi fare con quel vettore, ma non sarebbe più semplice assegnare più di uno slot per ogni dato?
Per esempio, assegnando due slot (char) potresti distinguere 2^16 configurazioni invece che 2^8 semplicemente mettendo nel primo le due cifre esadecimali più significative, nel secondo le due meno significative.
Magari una soluzione del genere potrebbe esserti più utile se non vuoi modificare troppo il tuo codice.
fantoibed
28-12-2004, 19:31
Originariamente inviato da end.is.forever
Non so cosa ci devi poi fare con quel vettore, ma non sarebbe più semplice assegnare più di uno slot per ogni dato?
Per esempio, assegnando due slot (char) potresti distinguere 2^16 configurazioni invece che 2^8 semplicemente mettendo nel primo le due cifre esadecimali più significative, nel secondo le due meno significative.
Più banalmente, come ho già detto, basta prendere un array di unsigned int invece che di unsigned char. Poi è tutto banale:
unsigned int messaggio[100];
unsigned char lettera, i;
...
if (messaggio[i]>255){
printf("messaggio[%d] = %d\r\n", i, messaggio[i]);
}else{
lettera = (unsigned char) messaggio[i];
printf("messaggio[%d] = %d cioè %c\r\n", i, messaggio[i], lettera);
}
...
Scusa se dovessi aver cannato qualcosa ma non ho voglia di aprire un compilatore... ;-) Se ci sono errori che non riesci a correggere da solo dimmi, che apro il visual C... ;-)
allora via "cast" nulla da fare a parte un warning su gcc ( visual manco se ne accorge ...)
la soluzione "parziale e incompleta " che ho trovato e' usare lo shift come segue :
packet_info[19]=(unsigned char)1233;
packet_info[20]=(unsigned char)1233>>8;
dovrei trovare ora una funzione che mi dica
34 e' grosso 1 byte;
1233 e' grosso 2 byte;
K e' grosso N byte
poi faccio un for del tipo:
// X e' la posizione del vattore da cui partire a scrivere il valore intero
for (i=0;i<N;i++)
{
vettore[ i + x]= valore_intero >> ( 8 * i ) ;
}
che ne dite ?
AnonimoVeneziano
31-12-2004, 15:53
Originariamente inviato da fantoibed
Stai facendo un casino incredibile. Stiamo parlando di linguaggio C e non di architetture. I tipi di dati sono definiti dagli standard:
* char -128 to +127 8bit
* unsigned char 0 to +255 8bit
* short -32768 to +32767 16bit
* unsigned short 0 to +65535 16bit
* long -2 147 483 648 to +2 147 483 647 32bit
* unsigned long 0 to +4 294 967 295 32bit
* int -32768 to +32767 16bit
or
* int -2 147 483 648 to +2 147 483 647 32bit
* unsigned int 0 to +65535 16bit
or
* unsigned int 0 to +4 294 967 295 32bit
* float ??? 32bit
* double ??? 64bit
* long double ??? 80bit
or
* long double ??? 64bit
Che tu compili un programma per farlo girare su un pentium, su un PIC16F86 su un ATMEL, su un ARM, su un Itanium o su un TI sono comunque cazzi del compilatore quelli di utilizzare i registri che quel dato processare ha per poter memorizzare certi tipi di dato, ma i tipi di dato sono questi.
Li trovi su qualsiasi libro di C!!!
Probabilmente fai casino con l'architettura dei processori, ma il linguaggio C è tutt'altra cosa.
Qui ti sbagli .
Ogni architettatura ha la sua dimensione tipo di INT .
Su un sistema a 32bit la dimensione di un INT in C è 32bit ,ossia 4 bytes , su un 286 erano 16bits ossia 2 bytes .
Mi sembra che sei te ches tai facendo un po' di confusione .
Anche perchè avrebbe poco senso su un sistema a 64 bit usare ancora int a 16 bit o "long int" a 32bit , non ti sembra?
Ciao
fantoibed
31-12-2004, 15:53
Originariamente inviato da honny
allora via "cast" nulla da fare a parte un warning su gcc ( visual manco se ne accorge ...) Che warning? Puoi incollarlo? :)
dovrei trovare ora una funzione che mi dica
34 e' grosso 1 byte;
1233 e' grosso 2 byte;
Se inizialmente a viene dichiarato come intero, sia 34 che 1233 occuperanno 2 bytes . Controlla con sizeof(a).
Il fatto che il 34 si riesca a far stare in un byte mentre 1233 no, è un'altra cosa. Puoi implementare un controllino del tipo:
If (a>0xff){
// a occupa 2 bytes
}else{
// a sta tutto in un byte
}
K e' grosso N byte
poi faccio un for del tipo:
// X e' la posizione del vattore da cui partire a scrivere il valore intero
for (i=0;i<N;i++)
{
vettore[ i + x]= valore_intero >> ( 8 * i ) ;
}
che ne dite ? Opsss, :ops:
Potevo già farti il caso generico di N bytes. Vabbè, la prossima volta. Ma, per curiosità, che programma è? Cosa dovrebbe fare e a cosa dovrebbe servire?
/\/\@®¢Ø
02-01-2005, 19:24
Originariamente inviato da fantoibed
Stai facendo un casino incredibile. Stiamo parlando di linguaggio C e non di architetture. I tipi di dati sono definiti dagli standard:
* char -128 to +127 8bit
* unsigned char 0 to +255 8bit
* short -32768 to +32767 16bit
* unsigned short 0 to +65535 16bit
* long -2 147 483 648 to +2 147 483 647 32bit
* unsigned long 0 to +4 294 967 295 32bit
* int -32768 to +32767 16bit
or
* int -2 147 483 648 to +2 147 483 647 32bit
* unsigned int 0 to +65535 16bit
or
* unsigned int 0 to +4 294 967 295 32bit
* float ??? 32bit
* double ??? 64bit
* long double ??? 80bit
or
* long double ??? 64bit
Come ha gia' fatto notare AnonimoVeneziano, la confusione la stai facendo tu. In C la dimensione dei tipi fondamentali dipende dalla macchina (e ambiente) su cui compili il programma, secondo la regola informale 'la dimensione del tipo e' quella piu' adatta su tale architettura'. Di conseguenza per programmi che girano in modalita' a 32bit la dimensione di un intero sara' quasi sicuramente di 32bit, e di 16bit nel caso di programmi compilati per cpu a 16bit.
L'unica costante quasi universale e' la dimensione di 8 bit per un char.
Non ho sottomano un manuale C, ma su quello C++ (e su queste cose in linea di massima i due linguaggi coincidono), presa come costante 'sizeof(char)==1' valgono le seguenti relazioni
1 = sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long)
1 <= sizeof(bool) <= sizeof(long)
sizeof(float) <= sizeof(double) <= sizeof(long double)
Inoltre un char deve essere di almeno0 8 bit, uno short di almeno 16, e un intero di almeno 32bit
/\/\@®¢Ø
02-01-2005, 19:34
Originariamente inviato da honny
allora via "cast" nulla da fare a parte un warning su gcc ( visual manco se ne accorge ...)
Certo che ti emette un warning, visto che stai facendo una operazione pericolosa e spesso sbagliata (ma che nel nostro caso e' probabilmente la soluzione giusta).
la soluzione "parziale e incompleta " che ho trovato e' usare lo shift come segue :
packet_info[19]=(unsigned char)1233;
packet_info[20]=(unsigned char)1233>>8;
dovrei trovare ora una funzione che mi dica
34 e' grosso 1 byte;
1233 e' grosso 2 byte;
K e' grosso N byte
poi faccio un for del tipo:
// X e' la posizione del vattore da cui partire a scrivere il valore intero
for (i=0;i<N;i++)
{
vettore[ i + x]= valore_intero >> ( 8 * i ) ;
}
che ne dite ?
Quando rileggi come fai a sapere quanti byte ti servono ? Ad esempio in che modo distingui il valore 0xFFFF da due valori distinti 0xFF e 0xFF.
Ti conviene partire dal presupposto che lavori sempre con interi da 32 bit (ad esempio) e salvi sempre tutti e 4 i byte.
fantoibed
02-01-2005, 19:41
Originariamente inviato da /\/\@®¢Ø Non ho sottomano un manuale C, ma su quello C++ (e su queste cose in linea di massima i due linguaggi coincidono), presa come costante 'sizeof(char)==1' valgono le seguenti relazioni
1 = sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long)
1 <= sizeof(bool) <= sizeof(long)
sizeof(float) <= sizeof(double) <= sizeof(long double) Uhm, sì è vero. C'erano imprecisioni nel mio discorso... :ave:
Originariamente inviato da /\/\@®¢Ø Inoltre un char deve essere di almeno0 8 bit, uno short di almeno 16, e un intero di almeno 32bit Questo è plausibile, ma è in contrasto con l'affermazione di AnonimoVeneziano :
Originariamente inviato da AnonimoVeneziano
Su un sistema a 32bit la dimensione di un INT in C è 32bit ,ossia 4 bytes , su un 286 erano 16bits ossia 2 bytes .
Mi sembra che sei te ches tai facendo un po' di confusione . Allora, l'int è almeno a 32bit come dici tu oppure è di 16bit sui 286 come dice lui? Cercando in rete ho trovato che gli int hanno sempre la stessa dimensione della word del processore.
Eppure esistono short int e long int rispettivamente a 16bit e 32bit sia sui 286 che sui Pentium...
Per i 64bit, invece, hanno inventato i long long int, ma allora un int su un Athlon64 equivale ad un long long ? Mah!
/\/\@®¢Ø
02-01-2005, 19:49
Originariamente inviato da fantoibed
Uhm, sì è vero. C'erano imprecisioni nel mio discorso... :ave:
Questo è plausibile, ma è in contrasto con l'affermazione di AnonimoVeneziano :
Allora, l'int è almeno a 32bit come dici tu oppure è di 16bit sui 286 come dice lui? Cercando in rete ho trovato che gli int hanno sempre la stessa dimensione della word del processore.
Eppure esistono short int[/b] e [i]long int rispettivamente a 16bit e 32bit sia sui 286 che sui Pentium...
Per i 64bit, invece, hanno inventato i long long int, ma allora un int su un Athlon64 equivale ad un long long ? Mah!
Ho sbagliato a riportare, chiedo scusa,
e' un long che e' almeno 32 bit
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.