Qual é o tamanho de um enum em C?


Melhor resposta

Um enigma muito espinhoso, quando é preciso combinar os deslocamentos da estrutura através dos limites da máquina ou protocolos de rede . A especificação diz que o tamanho deve ser o mínimo necessário para representar o maior valor que pode assumir. Portanto, um enum de estado de máquina de estado típico, por exemplo, pode exigir apenas um byte.

Existem AFAIK apenas três maneiras de controlar o tamanho:

alguns (mas não todos) compiladores têm uma opção de compilador para forçar o tamanho para sizeof (int) ou para 32 bits. A sintaxe do switch não é a mesma entre, digamos, MSC e gccc / clang.

A segunda maneira, se você precisar preencher um campo de 16 bits, é definir um valor máximo fictício que requer esse tamanho.

A outra maneira é usar estilos regulares de int nas definições de estrutura, mas então se dispensa a conveniência do depurador de mostrar o valor por nome de enum e, em vez disso, obter apenas inteiros.

Então, provavelmente será necessário especificar que a estrutura que contém o enum é compactada, não preenchida.

Resposta

Se nenhuma parte de alguma variável x é const ou , e x não é do tipo array, então a declaração…

x = x;

… praticamente não faz nada. Está bem formado. Supondo que x tenha sido inicializado de antemão, ¹ também está bem definido. A atribuição não realmente mudar o estado do programa, com algumas exceções potenciais (veja abaixo).

Isso é verdade mesmo se x tiver um struct tipo.

struct foo {

char buf[42];

int x;

};

struct foo x = { "Hello World", 18 };

x = x; // no big deal.

Então, qual é o “erro”? Não é um código útil , mas há uma grande quantidade de código que se encaixa nessa descrição. É apenas um erro se você pretendia fazer outra coisa e errou.

[Adendo: Dada a inutilidade desta atribuição, os compiladores estão inclinados a avisar sobre isso, uma vez que “é bastante provável que você tenha significa outra coisa.]

Por que essa parte sobre const e ? A restrição em const é simples: significa “somente leitura” e, portanto, você não pode “escrever nele. Pelo menos, não com atribuição simples.

Aquele que diz respeito a é mais complicado. Essa palavra-chave diz que o valor qualificado por ela pode ser modificado de maneiras não visíveis para a implementação e que a gravação nele pode ter efeitos colaterais. Sem cavar em um buraco de rato aqui, na prática, as únicas operações razoavelmente bem definidas que você pode realizar em um objeto volátil têm a seguinte aparência:

volatile int v;

int i;

i = v; // reads from v once, places into i.

v = i; // writes to v once with the contents of i.

Você pode fazer um pouco mais do que isso sensatamente com , mas apenas ligeiramente. Esse é um assunto para outro dia. Há um motivo pelo qual o C ++ 20 tornou-se obsoleto, exceto alguns usos de . Suas alterações parecem bastante razoáveis.

Mencionei algumas exceções possíveis acima. Jonas Oberhauser me lembrou que qualquer preenchimento em um struct é não necessariamente preservado por essa atribuição.

Além disso, é teoricamente possível que a representação subjacente para objetos possa mudar devido à atribuição, se o mesmo valor puder ser representado de várias maneiras.

Felizmente, seu programa é insensível a ambas as possibilidades. Se você alguma vez olhar para a representação subjacente do objeto, no entanto, poderá ver diferenças. Funções como memcmp podem notar, por exemplo. Da mesma forma, se você empregar trocadilhos.

¹ E se não foi, bem-vindo ao comportamento indefinido, já que você provavelmente entrou em conflito com um destes:

  • O valor de um objeto com duração de armazenamento automático é usado enquanto for indeterminado ( 6.2 .4 , 6.7.9 , 6,8 ).
  • Um lvalue designando um objeto de duração de armazenamento automático que poderia ter sido declarado com a classe de armazenamento de registro é usado em um contexto que requer o valor do objeto designado, mas o objeto não foi inicializado. ( 6.3.2.1 ).

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *