Newsgroup: it.comp.lang.c
Titolo: trattare array come struttura e viceversa

Salve a tutti,
supponendo di dover mandare un frame sulla porta seriale, e che il
messaggio sia composto da vari campi
di tipo eterogeneo, esiste un modo simile alla struct (comoda ad
esempio in fase di composizione del frame) ma che al contrario di essa
mi dia la possibilità di accedere anche all'intero frame come array
(comodo ad esempio in fase di trasmissione)?
Ringrazio anticipatamente tutti.

 Ringrazio anticipatamente tutti.
Se capisco bene, basta che converti il puntatore alla struct in un 
puntatore a char (o al tipo con il quale vuoi fare l'array). Il 
puntatore a char si comporta quindi come un array.
E.


Usando i cast e la macro offsetof.
Ciao
Giovanni
-- 
   A computer is like an air conditioner,
   it stops working when you open Windows.
   < 
http://giovanni.homelinux.net/
 >

 wrote:

Ciao Giovanni,
conosco offsetof ma proprio non riesco a vedere come potrei usarlo in
una macro,
potresti gentilmente darmi uno spunto su come intendi strutturarla,
grazie ancora per l'aiuto.

 E.
Ciao Manu,
avevo già pensato a questa ipotesi, ma c'è un problema:
questo tipo di trattamento della struct può funzionare su certi
sistemi,
ma non è detto, infatti nessuno garantisce che i campi della struct
siano contigui,
ti faccio un'esempio, se l'architettura indirizza 16bit alla volta, e
la tua struttura è formata
da due campi di cui il primo è un int e il secondo un char, l'array
risultante sarebbe non di 3 ma di 4 byte
in particolare i primi due contenenti l'int il quarto il char e il
terzo un bite di riempimento
inserito a discrezione del compilatore.
lo stesso dicasi se costruisco una unione tra un'array della
dimensione del frame in questione e la struct del frame,
in questo modo la union risultante occuperebbe in memoria quanto
l'array che devo indirizzare e potrei addirittura
accedere all'array indirizzandolo dalla union senza dover neanche fare
il cast.
Resta comunque il problema dell'allineamento di cui parlavo sopra.
Grazie comunque della risposta.

 Grazie comunque della risposta.
Dipende da quello che ci devi fare. Io mi immagino che tu voglia un 
array per poter utilizzare delle funzioni che guardano solo lo stato 
della memoria, e che non deve interpretare i valori contenuti (ad 
esempio per serializzare i dati).
Per sapere l'occupazione totale della struct (compresi eventuali byte di 
riempimento) puoi tranquillamente utilizzare sizeof. Se ti serve 
l'offset dei valori mi pare che Giovanni ti abbia dato la risposta.
E.

 E.
non è tanto importante la dimensione della struct quanto che i dati
nell'array ottenuto siano contigui
senza cioè i riempimenti introdotti dalla conversione.
Se cosi fosse bisognerebbe copiare l'array con i buchi in uno nuovo
senza buchi,
ma questo sarebbe un consumo di memoria inaccettabile per il micro.
Per ora quindi che l'unica soluzione consiste nel rinunciare alla
struct e usare un normalissimo array,
essendo l'unica struttura ,che conosco, che garantisce la compattezza
dei dati e rinunciare quindi
alla leggibilità del codice fornita da una rappresentazione
strutturata.
spero di esserermi spiegato.
Se dovessi fare una funzione come mi suggerivi che guarda solo lo
stato della memoria non potrei farlo,
non sapendo dove sono situati i buchi per evitarli ,a meno di non
conoscere la struttura dei campi.
Ancora grazie.

 struct e usare un normalissimo array,
Non mi pare proprio che questa sia una soluzione utile. Se puoi mettere 
i dati nell'array, li puoi mettere allo stesso modo nella struct. 
Sicuramente il tuo processore ti permette di specificare quanti bit 
utilizzare per ogni dato della struct e addirittura potresti far ricorso 
ai campi di bit, se veramente il tuo scopo � quello di risparmiare 
memoria. Anche solo cambiando l'ordine dei campi, di solito riesci a 
ridurre al minimo i problemi di allineamento.
E.

 ridurre al minimo i problemi di allineamento.
non posso usare la struct, nemmeno usando i bitfield, e nemmeno
cercando di
chiedere al preprocessore di compattare i field(perchè il mio non lo
supporta),
e nemmeno cambiando l'ordine, perchè significa cambiare la strutura
del frame
inviato sulla seriale (cioè cambierei il protocollo per intenderci).
Comunque l'unica soluzione che ho pensato è:
faccio una struct di puntatori e li faccio puntare ai campi
dell'array.
A rivederci.

dunss...@gmail.com
 ha scritto:

Che tipo di compilatore usi che non supporta l'allineamento? Mi sembra 
strano.
Comunque in genere si fa come nell'esempio sotto.
Ciao
es.
// prima
#if defined (__BORLANDC__)
   #include <pshpack1.h>
   #pragma nopackwarning
#elif defined(_MSC_VER)
   #pragma pack(push, 1)
#else
   // direttive per tuo specifico compilatore
   #error Occorre definire l'allineamento a 1 byte per le strutture seguenti
#endif
//--------------------
struct tuastruct {
	....
};
//--------------------
// dopo
#if defined (__BORLANDC__)
   #include <poppack.h>
   #pragma nopackwarning
#elif defined(_MSC_VER)
   #pragma pack(pop)
#endif

 Ringrazio anticipatamente tutti.
Ciao,
hai provato a creare una union tra la struct e l'array per poi usare, su 
  necessit�, l'una o l'altro?

 strutturarla, grazie ancora per l'aiuto.
Questo esempio è come inserire e/o estrarre da un array di caratteri i 
fields di una struttura.  Tuttavia se lo scopo è quello di trasmettere 
un pacchetto di dati IMO la soluzione migliore è quella di fare una 
struttura packed e quindi trasmettere direttamente la struttura.
Questo è quanto viene tipicamente fatto anche quando si devono 
riempire od estrarre i pacchetti per la rete proprio perché i due 
interlocutori potrebbero lavorare con compilatori e/o sistemi diversi.
#include <stddef.h>
#include <stdio.h>
struct buff_s {
   int a;
   int b;
   char ch[10];
   long d;
} buffer = {
   1, 2, "stringa", 12345678,
};
int main(void)
{
   long num;
   int off;
   char * buff = (char *) &buffer;
   off = offsetof(struct buff_s, d);
   /* estrae un field della struttura */
   num = *((long *)&(buff[ offsetof(struct buff_s, d) ]));
   /* assegna un campo in un array come fosse una struct */
   *((long *)&(buff[ offsetof(struct buff_s, d) ])) = num;
   printf("fieid d offset = %d \n", off);
   printf("fieid d value  = %ld \n", num);
   return 0;
}
Vedi anche l'implementazione del cliente per dhcp al link:
http://giovanni.homelinux.net/cgi-bin/index.cgi?/development/index.html
È una implementazione per Minix dove il compilatore impacchetta gli 
elementi della struttura di default.  I pacchetti devono essere 
riempiti direttamente a tutti i livelli dello stack tcp/ip.


   necessità, l'una o l'altro?
si è la stessa idea che dicevo a manu
e in effetti funziona, ma non è detto
infatti c'è sempre il problema della struct che puo contienere buchi
di riempimento.
Invece oggi ho fatto questo che funziona e credo risolva il problema.
union {
  struct{
  unsigned char* campo1;
  unsigned char* campo2;
  };
  unsigned char array[20];
}mioArrayConCampi = {
    (unsigned char*)&mioArrayConCampi.array[0],
    (unsigned char*)&mioArrayConCampi.array[15]
};
Sarebbe stato bello poterlo definire come tipo in modo da non dover
inizializzare ogni volta che serve un nuovo array cosi diviso andare a
scriverlo.
ma questo proprio credo non si possa fare .
Comunque grazie a tutti per le idee!

 
dunssco...@gmail.com
 ha scritto:

non supporta il pack per quello che ho capito..
è il compilatore iar per la famiglia msp430 di micro della texas.
stasera guardo per bene il manuale e provo come hai detto tu
poi ti faccio sapere.
Grazie infinite per l'aiuto.

>
<snip...>

Non capisco il tuo problema. Devi comunicare con un micro da cosa? da 
pc? Allora adatti il programma del pc ad avere l'allineamento giusto 
usato dal micro (se il suo compilatore non ha la capacità 
d'allineamento). Eventualmente, se il micro ha un suo allineamento, 
cerchi di aggiustare la struttura dati in modo da avere meno buchi 
possibili. Non penso che siano uno o due byte di padding a dare problemi.
Se poi il micro non è allineato al byte, usare una struttura compatta 
allineata al byte ti crea solo problemi (a meno di usare direttive tipo 
_unaligned in ARM, con la conseguenza di pesanti rallentamenti).
Ciao

 Ciao
Ciao.

 };
Non riesco proprio a capire di quale problema questo codice possa essere 
la soluzione... comunque se hai risolto, tanto meglio!
E.

> <snip...>







Secondo me stai guardando il problema dal lato sbagliato.
Tu non usi il compilatore iar della texas per il programma che gira sul pc.
micro-> compilatore iar-texas-> all. fisso (1-2-4 byte)
pc -> compilatore xxx -> imposti lo stesso del micro
ed avrai la struttura della stessa dimensione in entrambi
Piuttosto ci sarebbe da controllare l'endianess, se nel micro è big (e 
usi un pc standard -> little) devi swappare le word/dword.
Riguardo ai byte di padding intendevo che, se nel micro l'allineamento 
non è a byte, nella struttura potrebbero esserci dei buchi, non che 
dovessero essere di dimensioni diverse.
Ciao

 Ciao
Grazie a tutti
A presto.