Newsgroup: it.comp.lang.c
Titolo: sizeof();

scusate ma perche' se ho una struct di tipo
struct PROTO
{
   char    riconoscimento[5];
   BYTE id;
   BYTE idMittente;
   BYTE idRicevente;
   BYTE codeFunzione;
   BYTE lunghezzaDato;
   char *dato;
};
sizeof(PROTO); mi ritorna 16????
allora riconoscimento son 5 byte no??
poi ho altri 5 variabili byte, quindi siamo a 5+5=10,
e poi ho un puntatore, un puntatore non son 32bit?? quindi 5+5+4=14
cosa sbaglio???

cosa sbaglio???
nonportabilmente, tanto per capirci,
assumendo che tu stia compilando con un gcc:
<source>
typedef char BYTE;
struct PROTO
{
   char    riconoscimento[5];
   BYTE id;
   BYTE idMittente;
   BYTE idRicevente;
   BYTE codeFunzione;
   BYTE lunghezzaDato;
   char *dato;
};
struct PROT2
{
   char    riconoscimento[5];
   BYTE id;
   BYTE idMittente;
   BYTE idRicevente;
   BYTE codeFunzione;
   BYTE lunghezzaDato;
   char *dato;
} __attribute__((packed));
#include <stdio.h>
int main(void)
{
    printf("size of PROTO = %d\n", sizeof(struct PROTO) );
    printf("size of PROT2 = %d\n", sizeof(struct PROT2) );
    return 0;
}
</source>
<output>
 size of PROTO = 16
 size of PROT2 = 14
</output>
sbirish.

oltretutto dopo varie prove ottengo questi risltati:
struct PROVA
{
    BYTE x;
};
sizeof(PROVA) -> 1
struct PROVA
{
    BYTE x;
    char *y;
};
sizeof(PROVA) -> 8
struct PROVA
{
    char  z[2];
    BYTE x;
    char *y;
};
sizeof(PROVA) -> 8
struct PROVA
{
    BYTE x;
    char *y;
    char  z[2];
};
sizeof(PROVA) -> 12
come funziona sto sizeof!!! :o(
mi sembra impossibile che questo sia il corretto funzionamento, xo' non mi
pare neanche di utilizzarlo in modo sbagliato in fondo....

ho cercato qualcosa e ho capito...
Tnks....
pero' e' un bel casino allora...
infatti avevo da inserire una struttura in un bel buffer di char, e cosi non
riesco a fare niente!!!!
1) char *buffer = (char *) malloc (sizeof (STRUTTURA) );
    gia questa non funziona visto che potrebbe occuparmi piu byte di quelli
da occupare effettivamente....
2)char *buffer = (char *) malloc (DIMENSIONE_CALCOLATA_DA_ME);
   anche in questo modo non funziona visto che poi quando faccio il for per
copiare i dati:
   for(int i = 0; i < DIMENSIONE....; i++)
        buffer[i] = ((char *)&struttura)[i];
   vengono copiati anche i byte di padding (gisuto?) che non centrano nulla,
togliendo spazio ai byte da copiare effettivamente....
uff :o(

 togliendo spazio ai byte da copiare effettivamente....
I byte di padding vengono copiati,  ma non danno fastidio. Occhio che il
limite superiore di i deve essere sizeof(STRUTTURA). Ad esempio:
struct quux {
        char foo[2];
        int bar;
};
Supponi che il padding venga fatto in questo modo [1]:
struct quux {
        char foo[2];
        char padding[2];
        int bar;
};
con il tuo  ciclo copi anche i  due byte di padding  (che non contengono
informazioni utili) ma non sovrascrivi gli altri campi.
Btw, quel ciclo e` orrendo. Molto meglio cosi`:
char *buffer = malloc(sizeof(STRUTTURA));
memcpy(buffer, &struttura, sizeof(STRUTTURA));
ciao
Kronos
[1] Molto probabile se sizeof(int) == 4, in questo modo bar viene
allineato.
-- 
Home: 
http://kronoz.cjb.net
"Fare l'amore con dieci donne e` fantastico, soprattutto perche` ti
 presentano un sacco di amiche." -- Fabio Di Iorio


Niente, solo che nella struttura ci sono (nel tuo caso) 2 byte di 
padding. Non ci puoi fare niente (portabilmente), funziona cosi' perche' 
  probabilmente il tuo compilatore allinea le variabili a indirizzi 
multipli della loro dimensione, o perche' non si puo' fare altrimenti, o 
perche' cosi' e' piu' veloce reperire i valori. E' una questione di 
hardware.
-- 
Enrico 'Trippo' Porreca

 cosa sbaglio???
Niente, solo che nella struttura ci sono (nel tuo caso) 2 byte di 


 pare neanche di utilizzarlo in modo sbagliato in fondo....
L'uso e' sbagliato, nel senso che non puoi fare sizeof(PROVA) senza un 
opportuno typedef. Per il resto e' giusto.
-- 
Enrico 'Trippo' Porreca

 Kronos
Grazie mille....
K

 hardware.
capito... ora mi rimane da capire come inviare questa struttura in rete...
;o)
sto' pensando di cambiare tutto e utilizzare da subito un array di char...
Grazie anche a te...
K

>char *buffer = malloc(sizeof(STRUTTURA));
Stai compilando C o C++? Secondo me e' C++, ecco perche' riesci a 
scrivere sizeof (STRUTTURA) invece di sizeof (struct STRUTTURA), ed ecco 
perche' ti da quell'errore: il cast e' richiesto solo in C++, e in C no, 
anzi e' una pessima idea.
-- 
Enrico 'Trippo' Porreca

 correttamente...
Stop. Non avevi detto che dovevi spedirli in rete. In questo caso il tuo
problema  non e`  il  padding, e`  tutto il  resto. Cosa  succede se  la
comunicazione avviene tra un sistema big endiand ed uno little endian? E
se un sistema ha sizeof(int) == 4 e l'altro sizeof(2)? E se...?
Vale lo stesso discorso  che si fa per la scrittura  di file binari: non
farlo ;)
E` molto piu`  semplice inviare le informazioni in  ascii e riassemblare
la struttura dall'altra parte.
In alternativa  devi definirti  (tramite typedef) nuovi  tipi di  dati e
fare in  modo (tramite preprocessore o  quello che ti pare)  che le loro
dimensioni siano le stesse su tutte le piattaforme. Poi devi definire il
formato  per la  comunicazione (ie.  little  o big  endian? con  padding
oppure no?). Una volta  implementata la parte di basso  livello il resto
dell'applicazione potra` usarla per comunicare in maniera trasparente.
Kronos
-- 
Home: 
http://kronoz.cjb.net
"La teoria e` quando sappiamo come funzionano le cose ma non funzionano.
 La pratica e` quando le cose funzionano ma non sappiamo perche`.
 Abbiamo unito la teoria e la pratica: le cose non funzionano piu` e non
 sappiamo il perche`." -- A. Einstein

 anzi e' una pessima idea.
emh... in c++ ;o) pensavo si fosse capito anche dalla dichiarazione della
struct....
anche se cmq tutto il codice lo scrivo in c, apparte queste cosucce che
almente per la
dichiarazione di struct son piu comode...
cambia qualcosa???


Cambia il linguaggio!!!
Il problema e' che non stai 'scrivendo in C tutto tranne le 
dichiarazioni delle struct', ma stai scrivendo codice C++ che per una 
serie di motivi e' valido anche in C. Non ti aspettare che a sintassi 
uguale corrisponda risultato uguale, i due linguaggi sono diversi.
Ti consiglio *caldamente* di spostarti su it.comp.lang.c++ perche':
a) probabilmente riceverai risposte piu' appropriate, dato che qui non
    e' detto che qualcuno conosca il C++ (io stesso lo conosco davvero
    poco, e quanto ho detto sopra a proposito di struct e cast da void *
    lo so solo per coincidenza).
b) il discorso rischia di diventare off-topic (anzi... a dire il vero lo
    e' gia' a questo punto).
-- 
Enrico 'Trippo' Porreca


ancora una volta Grazie!!!

     e' gia' a questo punto).
bhe a questo punto mi sa che mi conviene scrivere tutto in c, visto
che non uso classi e che il c++ non lo conosco bene neanche io...
(non che sia un mostro del c :o)

 della struttura in ascii e poi inviarlo...
No, quello che fai e` interpretare la struttura come un array di char.
Data una struct del genere:
struct quux {
        int a;
        int b;
};
struct quux q = {123, 456};
dovresti  trasmettere trasmettere  (ad esempio)  "123 456"  in caratteri
(ie. {'1',  '2', '3',  ' ',  '4',  '5', '6'}),  non la  rappresentazione
binaria dei numeri 123 e 456. Poi  puoi creare un protocollo tutto tuo o
appoggiarti all'XML o quello che ti pare. L'importante e` che i dati non
vengano trasmessi nella loro rappresentazione binaria.
Kronos
-- 
Home: 
http://kronoz.cjb.net
Runtime error 6D at f000:a12f : user incompetente

 vengano trasmessi nella loro rappresentazione binaria.
Giusto, il fatto e' che la mia struttura contiene praticamente solo char:
typedef char BYTE;
struct PROTO
{
    char riconoscimento[5];
    BYTE id;
    BYTE id_mittente;
    BYTE id_ricevente;
    BYTE code_funzione;
    BYTE lunghezzaDato;
    char *dato;
};
di conseguenza non ho problemi di little/big endian (credo) e potrei gia
considerare questa
struttura come un array di char.. in fondo e' quello che e'...
e se non sbaglio, se ad esempio id e' = a 0, non mi serve neanche
convertirlo in '0' visto che e' cmq
sempre solo di un byte, no?!?
un ultima domanda poi non rompo piu' ;o)
mi fai capire meglio la cosa dell'xml??? o dirmi cosa devo cercare in
google, xke' non ho capito bene il nesso....
Tnks...

 Luca
un domani cambia compilatore e poi non e' piu' capace di compilare o capire
come mai non funziona come deve ... veramente bello quello che insegna VC e
la MS !!!
ciao

la MS !!!
__attribute__((packed))
belle cose che insenga la fsf.
mi sembra un discorso stupido. Lo standard ( purtroppo? ) non prevede
alcuna direttiva per l'allineamento, _ogni_ compilatore esistente ( e
ti sfido a trovarne uno che non abbia una estensione simile ) ha un
modo diverso di packare, visto che in alcuni ambiti è, se non
idealmente necessario, perlomeno molto conveniente avere una
estensione simile.
sbirish.

 estensione simile.
ma farlo su un buffer di char e con puntatori castati all'interno pare
brutto ??? basta che in send e in ricezione mandi tutti tipi a bit
conosciuti e come per magia li riavrai tutti nel buffer di char che poi
tratti come vuoi ... (cmq devi fare il controllo endian cmq dopo
l'estrazione)
non lo so' ma questa soluzione mi pare la piu' portabile senza doversi
sparare feature di compilatori ... e lo compili in modo uguale sotto VC che
sotto GCC che borland o qualsiasi altro ...
ciao

brutto ??? 
suppongo tu lo trovi comodo, buona tecnica, ed una grande idea.
Piuttosto, se vuoi restare nello standard, fai:
serialized_buffer* create_serialized_struct(my_struct*);
void  destroy_serialized_struct(serialized_buffer*); 
focalizzi perlomeno il problema in un unico punto senza aver bisogno
di propagare dei dettagli della tua implementazione.
sbirish.
--
beware of C hackers -- B.Meyer

Giusto, il fatto e' che la mia struttura contiene praticamente solo char:
Hai ragione, se hai solo char non hai problemi, se devi spedire numeri
guardati le funzioni hton* e ntoh*, sono quelle che ti tolgono dai
problemi di big/little endian. 

 google, xke' non ho capito bene il nesso....
Se  avessi dovuto  trasferire  strutture piu`  complesse avresti  potuto
usare  l'XML   (e  una  delle   tante  librerie  in   circolazione)  per
impacchettare i dati al posto che creare un protocollo da zero.
Kronos
-- 
Home: 
http://kronoz.cjb.net
Ci sono due cose che l'uomo non puo` nascondere:
essere ubriaco ed essere innamorato.

 Kronos
Oppure usare xdr, sviluppata da sun. Ci sono librerie e rfc a riguardo.
Luca

 di propagare dei dettagli della tua implementazione.
sai che mi hai tirato fuori una cosa che non sapevo ... dove sono scritti i
serializzed buffer cosi' da leggiucchiarci un po' ... ?
ciao e grazie io fino ad ora in protocollo di rete per levarmi il padding ho
sempre usato la via che ti ho detto ;-) e di errori non ne ho mai avuti ...