C: sizeof single struct member

Sto cercando di dichiarare una struttura che dipende da un’altra struttura. Voglio usare sizeof per essere sicuro / pedante.

 typedef struct _parent { float calc ; char text[255] ; int used ; } parent_t ; 

Ora voglio dichiarare una struct child_t che ha le stesse dimensioni di parent_t.text .

Come posso fare questo? (Pseudo-codice sotto.)

 typedef struct _child { char flag ; char text[sizeof(parent_t.text)] ; int used ; } child_t ; 

Ho provato diversi modi con parent_t e struct _parent , ma il mio compilatore non accetterà.

Come un trucco, questo sembra funzionare:

 parent_t* dummy ; typedef struct _child { char flag ; char text[sizeof(dummy->text)] ; int used ; } child_t ; 

È ansible dichiarare child_t senza l’uso di dummy ?

Anche se definire la dimensione del buffer con un #define è un modo idiomatico per farlo, un altro sarebbe usare una macro come questa:

 #define member_size(type, member) sizeof(((type *)0)->member) 

e usalo in questo modo:

 typedef struct { float calc; char text[255]; int used; } Parent; typedef struct { char flag; char text[member_size(Parent, text)]; int used; } Child; 

In realtà sono un po ‘sorpreso che sizeof((type *)0)->member) sia anche permesso come espressione costante. Roba forte.

Non sono nella mia macchina di sviluppo adesso, ma penso che tu possa fare una delle seguenti cose:

 sizeof(((parent_t *)0)->text) sizeof(((parent_t){0}).text) 

Edit : Mi piace la macro member_size che Joey ha suggerito di usare questa tecnica, penso che lo userei.

Utilizza una direttiva per il preprocessore, ovvero #define:

 #define TEXT_LEN 255 typedef struct _parent { float calc ; char text[TEXT_LEN] ; int used ; } parent_t ; typedef struct _child { char flag ; char text[TEXT_LEN] ; int used ; } child_t ; 

È ansible utilizzare una direttiva per il preprocessore per le dimensioni come:

 #define TEXT_MAX_SIZE 255 

e usarlo sia in genitore che in figlio.

Un’altra possibilità sarebbe quella di definire un tipo. Il fatto che tu voglia garantire la stessa dimensione per i due campi è un indicatore del fatto che tu abbia la stessa semantica per loro, penso.

 typedef char description[255]; 

e poi avere un campo

 description text; 

in entrambi i tipi.

struct.h li ha già definiti,

 #define fldsiz(name, field) \ (sizeof(((struct name *)0)->field)) 

così potresti,

 #include  /* EXIT_SUCCESS */ #include  /* printf */ #include  /* fldsiz */ struct Penguin { char name[128]; struct Penguin *child[16]; }; static const int name_size = fldsiz(Penguin, name) / sizeof(char); static const int child_size = fldsiz(Penguin, child) / sizeof(struct Penguin *); int main(void) { printf("Penguin.name is %d chars and Penguin.child is %d Penguin *.\n", name_size, child_size); return EXIT_SUCCESS; } 

ma, guardando nell’intestazione, sembra che si tratti di una cosa BSD e non di uno standard ANSI o POSIX. L’ho provato su una macchina Linux e non ha funzionato; utilità limitata.

soluzione c ++:

sizeof (Type :: member) sembra funzionare bene:

 struct Parent { float calc; char text[255]; int used; }; struct Child { char flag; char text[sizeof(Parent::text)]; int used; }; 

Sei libero di usare sizeof_field(type, filed) in Linux. È appena definito come segue:

 #define sizeof_field(type,field) (sizeof(((type *)0)->field)) 

questo è menzionato sopra. Ma è più portatile usare la macro già definita.

@ joey-adams, grazie! Stavo cercando la stessa cosa, ma per array non char e funziona perfettamente bene anche in questo modo:

 #define member_dim(type, member) sizeof(((type*)0)->member) / \ sizeof(((type*)0)->member[0]) struct parent { int array[20]; }; struct child { int array[member_dim(struct parent, array)]; }; int main ( void ) { return member_dim(struct child, array); } 

Restituisce 20 come previsto.

E, @ brandon-horsley, anche questo funziona bene:

 #define member_dim(type, member) sizeof(((type){0}).member) / \ sizeof(((type){0}).member[0])