Newsgroup: it.comp.lang.c
Titolo: struct di byte e interi

La dimensione di una struct formata da un intero e un byte è pari a 8
per problemi di
allineamento, supponendo che l'intero sia a 32bit.
Nel mio sistema devo assolutamente risparmiare memoria così non posso
permettermi
di sprecare byte per questi problemi di allineamento. Così ho pensato
di definire l'intero
nella struct come un array di 4 byte.
typedef struct {
  unsigned char x_arr[4];
  unsigned char y;
} mystruct;
In questo modo la struct occupa 5 byte, come volevo. Ma a questo punto
come faccio
ad accedere all'intero x in modo elegante nel codice? E' possibile
usare qualche
stratagemmo di macro o union che mi permette di scrivere:
mystruct foo;
int z;
foo.x = 10;
z = foo.x;
???
L'unica cosa che sono riuscito a fare è dichiarare una macro in questo
modo:
#define defx(s)  *(int *)&s.x_arr
ma l'esempio di prima diventerebbe:
defx(foo) = 10;
z = defx(foo);
Qualche soluzione migliore?

 
Non so cosa ci devi fare, ma io in questi casi,
se posso, memorizzo in un array gli int e in un array i
char. Cioe' scompongo la struttura in due array paralleli
nei quali la corrispondenza tra le componenti e' data
implicitamente dall'indice. Non e' detto che si possa fare nel
tuo caso.
Un'altra cosa da valutare e' l'uso di pragma o direttive
di compilazione per forzare il compilatore ad impaccare al
massimo i dati (questo dipende dal tuo compilatore).
Se la cosa e' possibile risolvi il problema alla radice.
Tieni anche conto che su certe architetture, se ricordo bene,
non e' proprio possibile trattare dati non allineati come
interi, cioe' per farci le operazioni sopra dovresti
comunque copiarli byte per byte in un vero intero, non basterebbe
fare cast degli indirizzi etc.etc.
Dati questi problemi intrisechi io non mi preoccuperei
tanto dell'eleganza del codice, quanto del fatto
che questo funzioni...
Un'altra possibilita' e' valutare se i bit dell'intero ti
servono tutti.
Se il numero fosse rappresentabile su 3 byte potresti usare
il quarto per il char, naturalmente al prezzo di lavorare
con shift binari e mascheramenti vari.
Diciamo che la risposta, a mio modo di vedere, dipende anche
molto dal tipo di elaborazione che vuoi fare e da quanti sono
i dati.
ciao,
g.

 Qualche soluzione migliore?
Non puoi usare una union ?
union ciao{
char a[4];
int x;
};
struct test {
ciao a;
char [a];


 }
Nel tuo caso, sizeof(struct test)=8... non risparmio niente.

 i dati.
Cioé? Come dovrei ragionare?

 Cioé? Come dovrei ragionare?
Non so come dovresti ragionare perche' appunto non conosco
i termini del problema. Bisognerebbe sapere, ad esempio, se oltre ai
vincoli di spazio hai anche vincoli di tempo di elaborazione,
se stai programmando per un sistema embedded o con un compilatore
tradizionale, in generale quanti sono i dati e che tipo di operazioni
ci devi fare sopra.
Per esempio, se di queste strutture devi usare un grosso array
oppure se fanno parte di una lista e vengono allocati dinamicamente
in piccole quantita', ma un numero elevato di volte: gli approcci
possono cambiare radicalmente.
ciao,
g.

 wrote in message
1140106772....@g44g2000cwa.googlegroups.com...
La dimensione di una struct formata da un intero e un byte è pari a 8
per problemi di
allineamento, supponendo che l'intero sia a 32bit.
Nel mio sistema devo assolutamente risparmiare memoria così non posso
permettermi
di sprecare byte per questi problemi di allineamento. Così ho pensato
di definire l'intero
nella struct come un array di 4 byte.
typedef struct {
  unsigned char x_arr[4];
  unsigned char y;
} mystruct;
In questo modo la struct occupa 5 byte, come volevo. Ma a questo punto
come faccio
ad accedere all'intero x in modo elegante nel codice? E' possibile
usare qualche
stratagemmo
Prova a vedere se il tuo compilatore ha la possibilità di riallineare la
grandezza della struttura, con
#include <pshpack?.h>
prima della struttura dove metti il valore desiderato al posto del ?  es: 2
#include <poppack.h>
per ripristinare l' allineamento di default...
una idea un p'ò strampalata che mi è venuta in mente, se non riesci a
trovare altre soluzioni, è quella di provare a utilizzare memcpy per copiare
il contenuto di x_arr in un intero senza segno di 4 byte... tenedo sotto
controllo con il debugger il codice effettivo generato... ma questa è più
che altro una curiosita momentanea che mi è balzata in testa sul momento,
non ho idea se per il linguaggio in questione sia legale...
Bye Dave.

In questo modo la struct occupa 5 byte, come volevo.
Non č affatto detto.  Nessuno ti assicura che una struct copra
esattamente la dimensione dei dati che contiene.  

 } mystruct;
#pragma pack (push, 1)
typedef struct {
	unsigned int x;
	unsigned char y;
} mystruct;
#pragma pack (pop)
Questo con GCC dovrebbe essere da 5 byte totali (no, non l'ho provato ma 
  sono programmatore di sistema e col pack ci lavoro piu' si' che no 
quindi tendo a fidarmi) e puoi accere ai campi secondo le dimensioni del 
loro tipo.
Oppure, come gia' ti suggeriva qualcuno, torni alla tua struct e, a 
parere mio molto poco elegantemente, dichiari un puntatore:
mystruct pippo;
unsigned int* x;
x = &(pippo.x);
e no, neanche questa l'ho provata ma se ho fatto qualche errore e' per 
te molto didattico correggerlo. :)
-- 
Morpheu5