C: modo migliore per fare sizeof (((SomeStruct *) 0) - > some_member)?
Domanda
Voglio ottenere le dimensioni di un membro specifico in una struttura.
sizeof (((SomeStruct *) 0) - > some_member)
funziona per me, ma sento che potrebbe esserci un modo migliore per farlo.
Potrei #define SIZEOF_ELEM (STRUCT, ELEM) sizeof (((STRUCT *) 0) - > ELEM)
e quindi utilizzare SIZEOF_ELEM (SomeStruct, some_member)
, ma mi chiedo se sia già integrato qualcosa di meglio.
Il mio caso d'uso specifico è in hsc2hs (collegamenti Haskell C).
pokeArray (plusPtr context (#offset AVFormatContext, filename)) .
take (#size ((AVFormatContext *) 0)->filename) .
(++ repeat '\NUL') $ filename
Soluzione
Quello che hai è più pulito che mai se non puoi garantire di avere una variabile di dereference. (Se puoi, usa solo sizeof (var.member)
o sizeof (ptr- > member)
, ovviamente, ma questo non funzionerà in alcuni contesti dove è necessaria una costante di compilazione.)
Tanto tempo fa (circa 1990), mi sono imbattuto in un compilatore che aveva " offsetof
" definito usando l'indirizzo di base 0, e si è bloccato. Ho risolto il problema hackerando < stddef.h >
per usare 1024 invece di 0. Ma non dovresti incontrare questi problemi ora.
Altri suggerimenti
Credo che tu abbia già la soluzione corretta lì. Potresti scavare il tuo stddef.h e cercare come è definito offsetof, dal momento che fa una cosa molto simile.
Ricorda che potrebbe esserci una differenza tra la dimensione di un membro e la differenza tra gli offset di quel membro e quello successivo, a causa del riempimento.
In C ++ puoi fare sizeof (SomeStruct :: some_member), ma questo è c e non hai un operatore per la risoluzione dell'ambito. Quello che hai scritto è buono come può essere scritto, per quanto ne so.
Microsoft ha i seguenti elementi in una delle loro intestazioni:
#define RTL_FIELD_SIZE(type, field) (sizeof(((type *)0)->field))
Non vedo alcun motivo per fare diversamente.
Hanno macro correlate per:
RTL_SIZEOF_THROUGH_FIELD()
RTL_CONTAINS_FIELD()
e la nifty:
CONTAINING_RECORD()
che aiuta a implementare elenchi generici nella C diritta senza dover richiedere che i campi dei collegamenti siano all'inizio di una struttura. Vedi questo articolo Kernel Mustard per dettagli.