Newsgroup: it.comp.lang.c
Titolo: struct e aree di memoria

Salve a tutti.
Vorrei allocare una zona di memoria che sia consecutiva ad una "struct".
Spiego meglio il problema ;o)
Fino ad ora utilizzavo una struttura di tipo
struct STRUTTURA
{
  int x;
  int y;
  char dato[64];
};
in questo modo potevo utilizzare
STRUTTURA struttura;
char *buffer;
buffer = (char *)&struttura
per ottenere una "stringa" contenente x,y,e dato, poi facendo l'operazione
inversa, e cioe',
struttura = *(STRUTTURA *) buffer;
 riottenevo la mia struttura originale...
ora pero' non mi basta piu un campo "dato" di lunghezza fissa e vorrei usare
una malloc, quindi
struct STRUTTURA
{
   int x;
   int y;
  char *dato;
};
solo che cosi facendo quando a dato gli assegno l'indirizzo dell'area di
memoria che alloco, questa non e' cosecutiva e
dovrei quindi crearmi un buffer anch'esso dinamico, copiarci nei primi 8
byte x e y, e poi copiarci di fila la zona puntata da dato.
non c'e' un modo per far si che le celle che alloco siano consecutive ad x e
y, considerando che x e y stanno pero' nello stack (credo)....
Grazie a tutti.

 y, considerando che x e y stanno pero' nello stack (credo)....
C'e` un "trucco":
struct STRUTTURA {
        int x;
        int y;
        char dato[];
};
Se ti serve un dato lungo 20 bytes:
struct STRUTTURA s = malloc(sizeof(struct STRUTTURA) + 20);
strcpy(s->dato, "blablabla");
Ecco i dettagli:
6.7.2.1 Structure and union specifiers
16 As a special case, the last element of a structure with more than one
named  member may  have  an  incomplete array  type;  this  is called  a
flexible array member. With two exceptions, the flexible array member is
ignored. First, the size  of the structure shall be equal  to the offset
of the  last element of  an otherwise identical structure  that replaces
the flexible array member with  an array of unspecified length.  Second,
when a .  (or ->) operator has a  left operand that is (a  pointer to) a
structure with a flexible array member  and the right operand names that
member, it  behaves as  if that  member were  replaced with  the longest
array (with  the same element  type) that  would not make  the structure
larger than  the object being  accessed; the  offset of the  array shall
remain that of the flexible array member, even if this would differ from
that of the replacement array. If this  array would have no elements, it
behaves as if  it had one element  but the behavior is  undefined if any
attempt is made to access that element or to generate a pointer one past
it.
17 EXAMPLE 
Assuming that all array members are aligned the same, after the 
declarations:
        struct s { int n; double d[]; }; 
        struct ss { int n; double d[1]; }; 
the three expressions:
        sizeof (struct s) 
        offsetof(struct s, d) 
        offsetof(struct ss, d) 
have the same value. The structure struct  s has a flexible array member
d.
18 If sizeof (double) is 8, then after the following code is executed: 
        struct s *s1; 
        struct s *s2; 
        s1 = malloc(sizeof (struct s) + 64); 
        s2 = malloc(sizeof (struct s) + 46); 
and assuming that the calls to malloc succeed, the objects pointed to by
s1 and s2 behave as if the identifiers had been declared as:
        struct { int n; double d[8]; } *s1; 
        struct { int n; double d[5]; } *s2; 
19 Following the further successful assignments: 
        s1 = malloc(sizeof (struct s) + 10); 
        s2 = malloc(sizeof (struct s) + 6); 
they then behave as if the declarations were: 
        struct { int n; double d[1]; } *s1, *s2; 
 
and: 
        double *dp; dp = &(s1->d[0]);   // valid 
        *dp = 42;                       // valid 
        dp = &(s2->d[0]);               // valid 
        *dp = 42;                       // undefined behavior 
20 The assignment: 
        *s1 = *s2; 
 
only copies the member n and not any of the array elements. Similarly: 
        struct s t1 = { 0 };            // valid 
        struct s t2 = { 2 };            // valid 
        struct ss tt = { 1, { 4.2 }};   // valid 
        struct s t3 = { 1, { 4.2 }};    // invalid: there is nothing for the 4.2 to initialize 
        t1.n = 4;                       // valid 
        t1.d[0] = 4.2;                  // undefined behavior
HTH,
Kronos
-- 
Home: 
http://kronoz.cjb.net
K.R.O.N.O.S
Kinetic Replicant Optimized for Nocturnal Observation and Sabotage

 y, considerando che x e y stanno pero' nello stack (credo)....
bhe se hai gia' piu' o meno un'idea di quanto sia il tuo max data puoi
inserirlo direttamente dentro la struct ed allocare il max e poi usare solo
quello che ti serve ... seno' non puoi :-p (ameno che di macchine mono
programmate e senza gestore della memoria dove puoi fare quello che vuoi tu)
ciao

 strcpy(s->dato, "blablabla");
scusami ma se allochi la struttura su s non dovresti usare s.dato ???
ciao

 strcpy(s->dato, "blablabla");
Questo pero' solo in C99.
-- 
Enrico 'Trippo' Porreca

 strcpy(s->dato, "blablabla");
A parte l'errore di cui sopra, questo 'trucco' funziona (ma solo in C99).
-- 
Enrico 'Trippo' Porreca

 scusami ma se allochi la struttura su s non dovresti usare s.dato ???
Manca l'asterisco... s e` un puntatore, non avrebbe alcun senso
altrimenti.
Kronos
-- 
Home: 
http://kronoz.cjb.net
Runtime error 6D at f000:a12f : user incompetente

 strcpy(s->dato, "blablabla");
wow, ora provo, anche se c'e' la fastidiosa cosa menzionata nell'altro
post... (padding)

 ha scritto nel messaggio
news:3F56243E...@lombardiacom.it...

Scusatemi ma
struct STRUTTURA *s;
questo è un puntatore chiamato s che puo puntare ad una variabile di tipo
STRUTTURA... e come mai
nell' esempio visto prima cioè strcpy(s->dato, "blablabla"); possiamo
riferirci al campo dato senza che a s è stato essegnato una variabile di
tipo struttura???
per riferirci al campo dato non dovevamo fare una cosa del genere?? :
struct STRUTTURA s, *sp;
sp = &s;
strcpy(sp->dato, "blablabla");
spero di essere stato abbastanza chiaro almeno lo spero... grazie per le
eventuali risposte
ciao :-P

 strcpy(sp->dato, "blablabla");
Questo non e' possibile in quanto non e' stata allocata memoria per il 
membro 'dato' della struct.
-- 
Enrico 'Trippo' Porreca

 strcpy(sp->dato, "blablabla");
cosi sp punta direttamente ad s, se ogni volta che crei un puntatore ad una
variabile, crei prima la variabile e poi fai puntare il puntatore ad essa
allora utilizza direttamente la variabile no??
quel che hai scritto tu e' sintatticamente giusto (forse neanche per
l'esempio in questione, visto che s.dato e' di soli 4 byte)
ma raramente (molto raramente credo) utile, con struct STRUTTURA s, viene
allocata un'area di memoria nello stack di dimensione sizeof(struct
STRUTTURA),
che quindi puoi gia utilizzare,
invece struct STRUTTURA *sp, alloca una variabile di 4byte, che poi per
poter essere utillizata come STRUTTURA dovra' puntare ad un'area di memoria
sufficientemente
grande per poter contenere STRUTTURA, e cio' puoi farlo sia facendola
puntare ad s:
sp = &s;
sia creando una nuova STRUTTURA con la malloc(sizeof(struct STRUTTURA));

 invece struct STRUTTURA *sp, alloca una variabile di 4byte
Chi l'ha detto che un puntatore e' di 4 byte? La dimensione dei tipi e' 
definita dall'implementazione, quindi quelli che per te sono 4 byte, per 
qualcun altro possono essere ad esempio 2 (vedi compilatori a 16 bit per 
MS-DOS in alcuni 'modelli di memoria').
Non solo, ma puntatori a tipi diversi possono anche avere dimensioni 
diverse.
-- 
Enrico 'Trippo' Porreca

 l'esempio in questione, visto che s.dato e' di soli 4 byte)
Rileggi meglio  il materiale che  ti postato. Il  campo dato ha  un tipo
incompleto, non viene allocata alcuna memoria per esso. In altre parole:
struct s1 {
        int a;
        char b[];
};
e` del tutto equivalente, dal punto di vista dello storage allocato, a:
struct s2 {
        int a;
};
Se usi  l'operatore sizeof su  s1 e su s2  vedrai che ti  restituira` lo
stesso numero.
Kronos
-- 
Home: 
http://kronoz.cjb.net
This message will self distruct in 5 seconds.

 stesso numero.
Postilla: sempre che non venga aggiunto padding finale alla struttura :)
In ogni caso non viene allocato spazio per l'array.
Kronos
-- 
Home: 
http://kronoz.cjb.net
Il dottore mi ha detto di smettere di fare cene intime per quattro.
A meno che non ci siamo altre tre persone.

 ha scritto nel messaggio
news:ifs5b.81506$sj6.1...@tornado.fastwebnet.it...

OK ma come fa poi a sapere cosa è 'dato'... cioè da dove prende 'dato'?  Non
c' è niente che gli dice dove 'dato' si trova e cosa è.
se io alloco qualcosa... mi viene restituito l' indirizzo del primo byte
allocato. Quindi questo non centra con la struttura. Quindi 's' non sa come
è fatta la struttura.
Mi sbaglierò sicuramente però questi sono i miei dubbi... grazie e ciao ;-)
ah....
 per badkill: ti ho inviato questo messaggio tramite e-mail e anche due
volte :-) Ho sbagliato a cliccare. ciao ;-)


si si avevo capito, io intendevo per l'esempio fatto da JSMR che facendo
STRUTTURA s,*sp;
sp = &s;
non alloca appunto, memoria per dato, e quindi non puo' poi copiarci dentro
"blablabla".....
per intenderci, col metodo che hai scritto tu, bisogna per forza utilizzare
la malloc....