Newsgroup: it.comp.lang.c
Titolo: Assegnare intero a due byte

Ciao a tutti,
ho un array di unsigned char che rappresenta il pacchetto da trasmettere 
su una seriale sincrona.
Questo array deve essere riempito con alcuni interi a 16 bit.
Una strada potrebbe essere la seguente:
unsigned char spi_buf[16];
unsigned int  value;
[...]
spi_buf[0] = (unsigned char) (value >> 8);
spi_buf[1] = (unsigned char) (value & 0xFF);
Esiste un metodo più elegante? Come prestazioni si può fare di meglio?
Parliamo di un modulo Rabbit (CPU a 16 bit).
Ciao e grazie!
Marco / iw2nzm

 Esiste un metodo più elegante? Come prestazioni si può fare di meglio?
Il tuo metodo mi piace molto, io però farei una union tra un int e un  
char[2] cosi' basta una sola assegnazione.
-- 
enos76

 char[2] cosi' basta una sola assegnazione.
Qualcosa del tipo:
unsigned char spi_buf[16];
unsigned int  value;
union {
	int integer;
	char chars[2];
} intchar2;
[...]
intchar2.integer = value;
Ma poi come faccio ad assegnare i due char nel mezzo dell'array spi_buf 
con un'unica istruzione?
A me verrebbe da fare:
spi_buf[0] = intchar2.char[0];
spi_buf[1] = intchar2.char[1];
Marco / iw2nzm

 dell'array spi_buf con un'unica istruzione?
Dimenticavo il buffer, scusa. Allora usa direttamente memcpy:
#include <string.h>
[...]
memcpy(&spi_buf[posizione], &numero_intero, 2);
Ciao
-- 
enos76

 memcpy(&spi_buf[posizione], &numero_intero, 2);
Ok grazie
Marco / iw2nzm


*((short int *) &spi_buf[0])) = value;
Ciao
Giovanni
-- 
   A computer is like an air conditioner,
   it stops working when you open Windows.
   Registered Linux user #337974  < 
http://giovanni.homelinux.net/
 >

 *((short int *) &spi_buf[0])) = value;
Interessante, grazie anche a te.
Dovrei vedere l'asm generato per capire se è più veloce del mio metodo.
Ciao!
Marco / iw2nzm

 Dovrei vedere l'asm generato per capire se è più veloce del mio metodo.
Puoi esserne sicuro che è più veloce.  Questa è una unica operazione 
di assegnamento come se spi_buf fosse un array di short int.  Devi 
solo fare attenzione agli indici se veramente lo vuoi usare in quel modo.


 
con questa non avviene il contrario ?
-- 
Per i buoni pensieri occorrono poche parole, soltanto
i cattivi si nascondono sotto un profluvio di chiacchiere.
                                             - W. Maurel -

 fare attenzione agli indici se veramente lo vuoi usare in quel modo.
Chiedo scusa se sono stato troppo veloce nel rispondere :-(
Il metodo che ti ho suggerito (ma anche gli altri descritti) vanno 
bene solo se la CPU che usi è BIG_ENDIAN.
Dall'esempio mostrato nel tuo primo post sembra che tu voglia 
memorizzare gli interi in 'network order".  Su una CPU tipo intel x86 
(LITTLE_ENDIAN) avresti i byte invertiti, cioè:
spi_buf[1] = (unsigned char) (value >> 8);
spi_buf[0] = (unsigned char) (value & 0xFF);
In genere per fare lo scambio si usano le funzioni o macro _htons e 
_ntohs, ma di solito sono implementate come macro poco efficienti.  Se 
hai la possibilità di inserire codice assembler ti suggerisco le 
seguenti funzioni (per CPU interl 16 bit) ancora più efficienti se il 
compilatore ouò generare le funzioni inline:
!!  unsigned short htons(unsigned short word);
!!  unsigned short ntohs(unsigned short word);
!!  Swaps byte order from host to network or from network to host
.define	_htons, _ntohs
_htons:
_ntohs:
	push	bp
	mov	bp, sp
	mov	ax, *4(bp)
	xchgb	al, ah
	leave
	ret
!!  unsigned long htonl(unsigned long dword);
!!  unsigned long ntohl(unsigned long dword);
!!  Swaps byte order from host to network or from network to host
.define	_htonl, _ntohl
_htonl:
_ntohl:
	push	bp
	mov	bp, sp
	mov	ax, *6(bp)	!!  high bytes of the long int
	mov	dx, *4(bp)	!!  low bytes of the long int
	xchgb	al, ah		!!  swap them, these are now low
	xchgb	dl, dh		!!  swap the others
	leave
	ret
Vedi 
http://giovanni.homelinux.net/development/
  all'interno del 
pacchetto "Network booting via ethernet - 16 bits code"


 
Giusto.  Vedi mia risposta precedente all'OP.


 spi_buf[0] = (unsigned char) (value & 0xFF);
Ho appena scoperto che per far comunicare correttamente i due micro devo 
invertire sia l'ordine dei byte (BIG / LITTLE ENDIAN) sia l'ordine dei 
bit perché la seriale sincrona funziona diversamente con le due CPU.
Allora ho usato il metodo qui sopra per invertire i byte e una look-up 
table per invertire i bit in ricezione sull'altro micro.
E ora comunicano che è un piacere :)
Marco / iw2nzm

 wrote in news:48e79b55$0$1072
$
4faf...@reader2.news.tin.it
:

cosi a occhio direi che e' piu' pesante fare memcpy che 2 assegnazioni...
Ciao Jack
-- 
http://motoko.dyndns.org
http://jack471.labrute.fr