Desenvolvimento - C/C++

Como pegar o sizeof de um membro de um struct...

Veja nesse artigo como pegar o sizeof de um membro de um struct sem alocar uma variável.

por Wanderley Caloni Jr



...sem alocar uma variável? Exemplo:

static const size_t FIELD_SIZE_MSGID = 15;

struct FEEDER_RECORD_HEADER
{
   char MessageID[FIELD_SIZE_MSGID];
   char MessageIndex[10];
};


// error C2143: syntax error: missing ")" before "."
char MessageIndexBuffer[sizeof(FEEDER_RECORD_HEADER.MessageIndex) + 1];

// error C2070: "": illegal sizeof operand
char MessageIndexBuffer[sizeof(FEEDER_RECORD_HEADER::MessageIndex) + 1];

Na primeira tentativa, até que bem-intencionada, é mais ou menos previsível que não funcione. O erro gerado pelo compilador não é sequer claro. O operador de acesso a membros (o ponto) precisa ter à sua esquerda alguma variável ou constante do tipo do struct que tem o membro acessado. Como o operando no caso é o nome do próprio tipo, nada feito. Mas valeu o teste. É muito importante ver as coisas acontecerem para que sejamos menos influenciados pelo poder da desinformação.

A segunda tentativa é mais próxima da realidade e de onde queremos chegar. O erro do compilador até nos dá uma dica! Nós acessamos o membro do struct certo, mas da maneira errada. Como o membro não é estático, ou seja, pertencente ao struct, não tem como acessar apenas pelo escopo. Precisamos de um objeto criado. Mas para termos um objeto criado supõe-se que devemos criá-lo. Ora, mas isso é exatamente o que NÃO queremos em nossa solução.

A Zona Morta do C++

Esse problema traz à lembrança uma curiosa particularidade no operador sizeof: ele NÃO avalia as expressões usadas como operandos. Como é isso? Bom, como o objetivo do sizeof é fornecer a quantidade de memória que a expressão ocupa, logo não faz sentido que ele também a execute. Muito lógico para uma linguagem que prima por eficiência e clareza, não? Se você quiser executar a expressão, basta colocá-la fora do sizeof também.

Sabemos então que nada que a gente coloque dentro de um sizeof vai ser realmente executado. É mais ou menos como a "zona morta" do c++, o lugar onde - se tratando de código executável - nada existe. Isso quer dizer que podemos construir um objeto lá dentro que na verdade ele não constrói! Vejamos o assembly de um negócio desses:

sz = sizeof( (new FEEDER_RECORD_HEADER)->MessageID );
// mov dword ptr [sz],0Fh

Nada é alocado, conseguimos o que queríamos. Isso mostra mais uma vez que a aparente "pequeneza" de algumas características da linguagem só se revelam fundamentais quando mais precisamos delas.

Artigo original: Caloni.com.br

Wanderley Caloni Jr

Wanderley Caloni Jr