C: modo migliore per fare sizeof (((SomeStruct *) 0) - > some_member)?

StackOverflow https://stackoverflow.com/questions/1014750

  •  06-07-2019
  •  | 
  •  

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
È stato utile?

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top