C: melhor maneira de fazer sizeof (((SomeStruct *) 0) -> some_member)?

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

  •  06-07-2019
  •  | 
  •  

Pergunta

Eu quero obter o tamanho de um membro específico em um struct.

sizeof(((SomeStruct *) 0)->some_member) trabalha para mim, mas eu sinto que pode haver uma maneira mais agradável para fazê-lo.

Eu poderia #define SIZEOF_ELEM(STRUCT, ELEM) sizeof(((STRUCT *) 0)->ELEM) e depois usar SIZEOF_ELEM(SomeStruct, some_member), mas gostaria de saber se já existe algo melhor built-in.

Meu caso de uso específico está em hsc2hs (emperramentos Haskell C).

pokeArray (plusPtr context (#offset AVFormatContext, filename)) .
  take (#size ((AVFormatContext *) 0)->filename) .
  (++ repeat '\NUL') $ filename
Foi útil?

Solução

O que você tem é tão limpo quanto ele ganha, se você não pode garantir que você tem uma variável para excluir a referência. (Se você pode, em seguida, usar apenas sizeof(var.member) ou sizeof(ptr->member), é claro, mas isso não vai funcionar em alguns contextos onde é necessária uma constante de tempo de compilação.)

Uma vez em cima de um longo, longo tempo atrás (circa 1990), eu corri para um compilador que tinha 'offsetof' definido usando o endereço de base 0, e ele caiu. Eu trabalhei em torno do problema cortando <stddef.h> a usar 1024 em vez de 0. Mas você não deve correr em tais problemas agora.

Outras dicas

Eu acredito que você já tem a solução correta lá. Você poderia desenterrar o seu stddef.h e procurar como offsetof é definida, uma vez que ele faz uma coisa muito similar.

Lembre-se que pode haver uma diferença entre o sizeof um membro e a diferença entre os offsetofs desse membro e o próximo, devido ao estofamento.

Em C ++ você poderia fazer sizeof (SomeStruct :: some_member), mas esta é c e você não tem operador de resolução de escopo. O que você escreveu é tão bom quanto pode ser escrito, tanto quanto eu sei.

Microsoft tem o seguinte em um de seus cabeçalhos:

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

Eu não vejo nenhuma razão para fazer diferente.

Eles têm macros relacionados para:

RTL_SIZEOF_THROUGH_FIELD()
RTL_CONTAINS_FIELD()

eo bacana:

CONTAINING_RECORD() 

que ajuda a implementar listas genéricas em linha reta C sem ter de exigir que os campos de link estar no início de um struct. Veja este Kernel Mustard artigo para mais detalhes.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top