Newsgroup: it.comp.lang.c
Titolo: Array di struct con inizializzazione

Ho una memoria (EEPROM) con spazio di indirizzamento lineare (da
0x0000 a 0xFFFF) in cui devo "allocare" alcune mie variabili (interi,
struct, array, ecc.) in modo statico. Per evitare di sprecare codice,
ho pensato ad un array di struct di questo tipo:
  struct data {
    unsigned int address;  /* Indirizzo nella memoria */
    size_t nbytes;  /* Dimensione dato in memoria */
    void *ptr;  /* Puntatore alla variabile relativa al dato in
memoria */
  }
  struct data *datalist[] = {
    { 0x0000, 3, var1 },
    { 0x0003, 4, var2 },
    { 0x0007, 1, var3 },
    { 0x0008, 5, var4 },
  };
E' ovvio che il primo campo di ogni elemento dell'array è la somma
dello stesso campo e di nbytes dell'elemento
precedente.
E' possibile, mediante preprocessore, automatizzare questo conteggio?


Non credo di aver mai visto un approccio simile. A che ti potrebbe mai
servire questa struttura? :O

 E' possibile, mediante preprocessore, automatizzare questo conteggio?
Certamente. Ti puoi fare un tool da eseguire prima della compilazione. 
Che difficolt� trovi?
Se vuoi usare il preprocessore del C � un'altro discorso, non mi pare 
riesci ad ottenere un sistema del tutto automatico, ma qualcosa che ti 
permette di inserire nuove variabile con relativa semplicit� pu� essere 
fatto in questo modo:
#define VAR_PIPPO_OFFSET 0
#define VAR_PIPPO_SIZE 4
#define VAR_PLUTO_OFFSET VAR_PIPPO_OFFSET+VAR_PIPPO_SIZE
#define VAR_PLUTO_SIZE 4
...
E.

 servire questa struttura? :O
Vediamo se mi spiego.
Su una scheda elettronica, dove gira il mio programma C, ho una EEPROM
a cui
posso accedere in lettura e scrittura e che mi serve per salvare, in
modo non volatile,
alcune variabili (non ho un hard-disk, né un filesystem) di vario
tipo.
All'accensione vado a leggere tutti i valori salvati e li metto nelle
variabili in RAM. Dovesse
servire, vado a salvare la variabile nella EEPROM.
Con l'array che descrivevo nell'altro post, raccolgo insieme tutte
queste variabili che
devono essere salvate in modo non volatile nella EEPROM. Quindi c'è
l'indirizzo in EEPROM,
la dimensione della variabile e il puntatore alla variabile.
Siccome in EEPROM posso "allocare" le variabili come voglio, ho
pensato all'approccio più
semplice: una variabile dopo l'altra, senza buchi. Questo vuol dire
che l'indirizzo in EEPROM
di una variabile è pari all'indirizzo in EEPROM della variabile
precedente più la sua dimensione.
Nella definizione dell'array di cui sopra, quindi, il primo campo è
calcolabile a priori in fase di
preprocessing. Vorrei evitarlo di scriverlo e calcolarlo a manina
perchè, cambiando uno qualsiasi
dei campi intermedi, dovrei ricalcolarmi tutti gli altri successivi.
Ho visto che funziona in questo modo:
  struct data {
    unsigned int address;
    size_t nbytes;
    void *ptr;
  }
  struct data *datalist[] = {
    { 0x0000, 3, var1 },
    { datalist[1].address + datalist[1].nbytes, 4, var2 },
    { datalist[2].address + datalist[2].nbytes, 1, var3 },
    { datalist[3].address + datalist[3].nbytes, 5, var4 },
  };
Così potrebbe andarmi bene e risolvo questo problema.
Però comunque non mi piace... ma per un altro motivo che è fuori da
questo topic.

   
Forse il motivo per cui non ti piace � quello che dicevo prima.
Se non ti fa senso usare roba non standard ed � accettabile schiaffare 
tutte le variabili in un'unica struttura, usando gcc su un x86 (per via 
delle assunzioni su lle dimensioni di char e long e per l'uso 
dell'attributo packed), potresti scrivere:
------------------------------
#include <stddef.h> /* Per avere offsetof, ma visto che usi size_t 
probabilmente c'e' gia' */
/* Tua definizione di struct data */
struct _eeimg {
   char var1[3];
   long var2;
  char var3;
  struct {
     char b;
     long L;
  } __attribute__((packed)) var4;
} __attribute__((packed)) eeimg;
struct data datalist[] = {
   {offsetof(struct _eeimg,var1),sizeof(eeimg.var1),&eeimg.var1},
   {offsetof(struct _eeimg,var2),sizeof(eeimg.var2),&eeimg.var2},
   {offsetof(struct _eeimg,var3),sizeof(eeimg.var3),&eeimg.var3},
   {offsetof(struct _eeimg,var4),sizeof(eeimg.var4),&eeimg.var4}
};
----------------------
Ovvio che se non usi gcc l'assurda notazione del gcc la dovrai 
sostituire con qualcos'altro.
Giovanni

 dei campi intermedi, dovrei ricalcolarmi tutti gli altri successivi.
si, ma MICA LO CALCOLI A MANO TU!! Lo fai calcolare a qualcos'altro.
Dai la lista delle variabili con la dimensione e ti genera in
automatico la lista dei #define.
Guarda che non e' difficile.
Ciao Jack