Newsgroup: it.comp.os.linux.development
Titolo: Convertire interi al formato "little endian"

Salve!
Per garantire la portabilità di un programma che sto ancora progettando,
avrei bisogno di  una funzione che converta degli interi  (long o short)
dal formato della macchina che esegue il programma al "little endian".
So che ci sono delle funzioni  che convertono dal formato locale al "big
endian" (htons,  htonl), ma non mi  risulta che ci siano  per il "little
endian". Al che ho provveduto io stesso ad implementarle in questo modo:
short htobs(short n)
{
        const int nbytes= sizeof(short);
        int i;
        unsigned char *tmp, *naddr;
        naddr= (unsigned char*)&n;
        tmp= (unsigned char*)malloc(nbytes);
        n= htons(n);
        for (i= 0; i < nbytes; i++)
        {
                *(tmp+nbytes-1-i)= *(unsigned char*)(naddr+i);
        }
        n= *(short*)tmp;
        free(tmp);
        return n;
}
La mia soluzione però non mi piace per diversi motivi:
- allocazione esplicita della memoria (inefficiente)
- aritmetica dei puntatori
- possibilità di memory-leaks
Praticamente ho messo insieme tutte le sporche possibili e immaginabili.
Avevo provato ad  usare degli array di unsigned char,  ma non ho trovato
un modo che fosse uno di fare il cast dello short in ingresso a un array
di unsigned char. Avete qualche suggerimento, o è proprio questo il modo
migliore di procedere? Stento a  crederci... magari c'è qualche funzione
della libc che mi sfugge...
-- 
  _      ___ ____
 | | /| / (_)_  /
 | |/ |/ / / / /_	ANTI-SPAM WARNING:
 |__/|__/_/ /___/	the e-mail address is fake.
 
Ti se'bbevuto... il... ciervello?

]

 di unsigned char. Avete qualche suggerimento
union u {
        unsigned short s;
        unsigned char c[2];
};
Ciao ciao,
Andrea
-- 
"...Unix, MS-DOS, and Windows NT (also known as the Good, the Bad, and 
 the Ugly)."
(by Matt Welsh)

};
Lo, so,  lo so, devo proprio  comprarmi urgentemente un libro  sul C. Ma
visto che al momento non ce l'ho  sotto mano (GIURO che lo compro, anche
perche`  ho iniziato  un progetto  piuttosto importante),  che significa
esattamente questa union?  Che viene allocato solo  lo spazio necessario
per contenere  il piu` grosso degli  elementi che la compongono  e posso
farci un cast a uno qualunque dei tipi di dati che contiene?
Se e` cosi`... beh, oggi ho imparato  qualcosa di nuovo, e mi sa che era
proprio quello che mi serviva. In ogni caso, grazie 1024. (-:
-- 
  _      ___ ____
 | | /| / (_)_  /
 | |/ |/ / / / /_	ANTI-SPAM WARNING:
 |__/|__/_/ /___/	the e-mail address is fake.
 
Porcello e` piu` bello. (Wiz)

dovrebbe andare bene):
[snipz]
Ti ringrazio, ma la mia necessita`  era un po' diversa. La procedura che
mi hai proposto  va bene se so  qual'e` il "byte sex"  della macchina su
cui compilo, ma il problema e` che io non lo so, o meglio, voglio che il
programma  scriva dei  numeri little  endian anche  su architetture  big
endian senza  modificare il codice. La  dritta di Andrea Foco  pero`, se
riesco a metterla in pratica, mi risparmiera` la malloc().
-- 
  _      ___ ____
 | | /| / (_)_  /
 | |/ |/ / / / /_	ANTI-SPAM WARNING:
 |__/|__/_/ /___/	the e-mail address is fake.
 
Beyond your innocence, your youth is gone. (R. Sambora)

cui compilo [...]
Scusami, non avevo capito bene... in realtà anche il tuo suggerimento mi
sarà utile per convertire da big  endian in little endian senza usare la
maledetta malloc(). Era un po' tardi ed ero un po' fuso. (-:
Ora che sono fresco vado subito a modificare il programma.
-- 
  _      ___ ____
 | | /| / (_)_  /
 | |/ |/ / / / /_	ANTI-SPAM WARNING:
 |__/|__/_/ /___/	the e-mail address is fake.
 
Il casino lo faccio apposta perche` sia chiaro. (P. Miglioli)

proprio quello che mi serviva. In ogni caso, grazie 1024. (-:
E prenditi il K&R2ed.
--
 (o-  | HomePage 
http://pinguin.linuxbox.com
 //\  | email: r.salmaso (at) 
flashnet.it
 V_/_ | email: pinguin (at) 
pinguin.linuxbox.com

riesco a metterla in pratica, mi risparmiera` la malloc().
Per sapere qual e' il byte sex puoi provare a vedere la #define
BYTE_ORDER, che dovrebbe essere definita in sys/param.h a
(BIG|LITTE)_ENDIAN; altrimenti puoi usare in fase di configurazione
qualche semplice test tipo:  
short dummy=0x1
#define LITTLE_ENDIAN (*(char*&dummy)&dummy)
Dovrebbere valere 1 se little endian e zero se big endian


 non farebbero nulla.
Non ho seguito la discussione dall'inizio, ma se includete la
<asm/byteorder.h> avrete a disposizione questa roba :
/*
 * The following macros are to be defined by <asm/byteorder.h>:
 *
 * Conversion of long and short int between network and host format
 *	ntohl(__u32 x)
 *	ntohs(__u16 x)
 *	htonl(__u32 x)
 *	htons(__u16 x)
 * It seems that some programs (which? where? or perhaps a standard? POSIX?)
 * might like the above to be functions, not macros (why?).
 * if that's true, then detect them, and take measures.
 * Anyway, the measure is: define only ___ntohl as a macro instead,
 * and in a separate file, have
 * unsigned long inline ntohl(x){return ___ntohl(x);}
 *
 * The same for constant arguments
 *	__constant_ntohl(__u32 x)
 *	__constant_ntohs(__u16 x)
 *	__constant_htonl(__u32 x)
 *	__constant_htons(__u16 x)
 *
 * Conversion of XX-bit integers (16- 32- or 64-)
 * between native CPU format and little/big endian format
 * 64-bit stuff only defined for proper architectures
 *	cpu_to_[bl]eXX(__uXX x)
 *	[bl]eXX_to_cpu(__uXX x)
 *
 * The same, but takes a pointer to the value to convert
 *	cpu_to_[bl]eXXp(__uXX x)
 *	[bl]eXX_to_cpup(__uXX x)
 *
 * The same, but change in situ
 *	cpu_to_[bl]eXXs(__uXX x)
 *	[bl]eXX_to_cpus(__uXX x)
 *
 * See asm-foo/byteorder.h for examples of how to provide
 * architecture-optimized versions
 *
 */
Le macro cpu_to_*() e *_to_cpu() sono quelle che fanno per voi. Sono
utilizzate anche nel kernel. Quindi potete stare tranquilli che funzionano :-)
Bye.

dal formato della macchina che esegue il programma al "little endian".
#ifdef __BIG_ENDIAN__
	unsigned short htobs(unsigned short n)
	{
		return (n>>8)|(n<<8);
	}
#else
	#define htobs(n)	(n)
#endif
Se non sai quant'e' il sizeof(short), qui si suppone 2, puoi fare:
unsigned short htobs(unsigned short n)
{
	size_t i = sizeof(unsigned short);
	unsigned short bs = 0;
	while(i--)	// O --i? Boh ;-)
	{
		bs=(bs<<8)|(n&0xFF);
		n>>=8;
	}
	return bs;
}
Leonardo
".signature": bad command or file name