HOWTO · C
Como usar typedef enum em C
Este artigo apresenta como usar typedef enum em C, explica os seus benefícios e fornece exemplos claros. Saiba como melhorar a legibilidade e a manutenção do código com typedef enum e descubra como usá-lo em structs. Quer seja um principiante ou pretenda aperfeiçoar as suas competências, este guia ajudá-lo-á a navegar pelos enums em C com facilidade.
Nesta página
Em C, um enum declara constantes inteiras nomeadas, e o typedef pode atribuir ao tipo enum um nome mais curto. Utilize os nomes para tornar os valores de estado e de opções mais fáceis de ler e, em seguida, trate esses valores explicitamente sempre que a entrada ou os dados armazenados possam vir de fora do seu programa. Um enum melhora a clareza, mas não valida automaticamente todos os valores atribuídos a uma variável.
Definir um enum e atribuir valores
Um enumerador sem um valor explícito começa em 0; cada enumerador seguinte é um maior do que o valor anterior. Por exemplo, enum { MONDAY, TUESDAY, WEDNESDAY }; atribui 0, 1 e 2. Pode atribuir valores explicitamente quando estes precisam de corresponder a um formato, protocolo ou conjunto estável de códigos existente: enum Status { STATUS_READY = 1, STATUS_RUNNING = 4, STATUS_DONE = 8 };. Após um valor explícito, o próximo valor implícito é um maior do que esse valor.
Nomes como STATUS_READY são constantes inteiras. Não são variáveis. Uma variável enum pode receber um valor diferente mais tarde, e o C geralmente não a restringe aos enumeradores listados na sua declaração. Trate os valores provenientes de entrada, ficheiros ou outras fontes externas como dados que precisam de ser verificados antes de os utilizar.
Criar um alias typedef para um enum
Uma etiqueta enum e um alias typedef são nomes relacionados, mas distintos. Com enum State { ... };, uma declaração utiliza enum State. Um typedef pode introduzir o alias mais curto State, permitindo declarações como State current;. O alias refere-se ao mesmo tipo; o typedef não cria um tipo distinto. A escrita combinada typedef enum State { ... } State; declara a etiqueta e o alias em conjunto.
Este exemplo pede um número inteiro, verifica se a leitura foi bem-sucedida e valida o valor antes de o converter para State e de o armazenar no campo de Job. Introduza 2 para ver o caminho de sucesso. O programa imprime o pedido e o valor repetido na mesma linha e, em seguida, o switch imprime Running. Se a leitura falhar ou o número estiver fora dos três estados suportados, o programa imprime uma mensagem e para antes da conversão.
#include <stdio.h>
typedef enum State {
STATE_READY = 1,
STATE_RUNNING = 2,
STATE_DONE = 3
} State;
typedef struct Job {
State state;
} Job;
int main(void) {
int input;
printf("Input: ");
if (scanf("%d", &input) != 1) {
puts("Could not read an integer.");
return 0;
}
printf("%d\n", input);
if (input != STATE_READY && input != STATE_RUNNING && input != STATE_DONE) {
puts("Unsupported state.");
return 0;
}
Job job = { (State)input };
switch (job.state) {
case STATE_READY:
puts("Ready");
break;
case STATE_RUNNING:
puts("Running");
break;
case STATE_DONE:
puts("Done");
break;
default:
puts("Unsupported state.");
break;
}
return 0;
}
Input: Could not read an integer.
Utilizar um tipo enum num struct
O struct Job acima armazena o seu estado num campo State. Isto mantém o estado junto aos outros dados que descrevem um job, enquanto as constantes enum tornam as atribuições e os casos do switch legíveis. Também pode declarar o campo com a etiqueta como enum State state; se optar por não definir um alias typedef.
Um struct não adiciona validação ao campo. Se o valor vier de uma fonte que possa fornecer um número não suportado, verifique-o antes de confiar nele. O ramo default oferece ao programa uma resposta definida quando o valor armazenado não corresponde a nenhum dos estados nomeados. Se uma aplicação específica necessitar de garantias mais rigorosas, valide no limite onde o valor entra no programa e mantenha essa verificação próxima da atribuição.
Escolher valores enum e utilizá-los em segurança
Utilize valores implícitos quando as constantes forem etiquetas internas e a sua representação numérica não importar. Atribua valores explicitamente quando outra interface exigir números específicos e mantenha essas atribuições estáveis se os dados forem guardados ou trocados. Em qualquer caso, as constantes nomeadas comunicam a intenção melhor do que literais inteiros sem explicação e oferecem aos responsáveis pela manutenção um único local para ver as etiquetas disponíveis.
Estes benefícios não tornam as variáveis enum só de leitura nem garantem que contenham apenas enumeradores nomeados. Uma variável pode mudar durante a execução, e uma conversão ou uma entrada externa pode produzir um valor sem nome correspondente. Utilize um switch com um ramo default ou valide o valor em relação aos enumeradores aceites antes de o processar. Isto impede que dados inesperados sigam silenciosamente um caminho destinado a um estado conhecido.
Em resumo, declare o enum para as constantes nomeadas, adicione um alias typedef quando este tornar as declarações mais claras e utilize o tipo resultante sempre que o estado pertencer, incluindo campos de struct e parâmetros de função. Escolha valores numéricos explícitos apenas quando os números fizerem parte de um requisito e mantenha a validação separada da conveniência de nomenclatura que os enums proporcionam.