Qual é o tamanho de uma enumeração em C?

140

Estou criando um conjunto de valores de enumeração, mas preciso que cada valor de enumeração tenha 64 bits de largura. Se bem me lembro, um enum geralmente é do mesmo tamanho que um int; mas achei que tinha lido em algum lugar que (pelo menos no GCC) o compilador pode fazer com que o enum tenha a largura necessária para manter seus valores. Então, é possível ter um enum com 64 bits de largura?

mipadi
fonte
1
Então, se eu entendi bem, 2 ^ 32 enums não são suficientes para você? Ou é uma preocupação de alinhamento, por que você precisa que sejam 64 em vez de 32, estou muito curioso.
Jokoon
1
@jokoon: Sinceramente, não me lembro mais. Eu acho que queria que as enumerações contivessem valores maiores que 2 ^ 32-1.
Mipadi
Um uso seria se você precisasse de uma união entre uma enumeração e um ponteiro.
Demi

Respostas:

97

Um enumsó é garantido para ser grande o suficiente para armazenar intvalores. O compilador é livre para escolher o tipo real usado com base nas constantes de enumeração definidas, para que ele possa escolher um tipo menor se puder representar os valores que você definir. Se você precisar de constantes de enumeração que não se encaixam em uma int, precisará usar extensões específicas do compilador para fazer isso.

Robert Gamble
fonte
12
Sua primeira frase parece entrar em conflito com a sua última. A restrição de que um enumdeve ser maior que um intou menor? Após a resposta de @MichaelStum, sua primeira frase deve ser "É enumgarantido que apenas um se encaixa em um intvalor".
HaskellElephant
Como um hack feio e sensível à implementação em duas plataformas de complemento (é o que todos os sistemas hoje em dia?), Você pode forçar um enum a ser tão grande quanto um int, garantindo que ele contenha valores negativos. Não é uma técnica recomendada.
persiflage
7
Essa resposta parece sugerir que um enum é tão grande quanto um int. A resposta de Michael Stum , que faz referência a C99, diz que um enum pode ser tão pequeno quanto um char.
precisa saber é o seguinte
3
A primeira frase desta resposta está incorreta. A enumsó é garantido para ser grande o suficiente para manter o valor da maior recenseador na enumeração.
MM
91

Retirado do atual C Standard (C99): http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf

6.7.2.2 Enumeração especificadores
[...]
Restrições
A expressão que define o valor de uma constante de enumeração deve ser uma expressão constante de número inteiro que tem um valor representável como um int.
[...]
Cada tipo enumerado deve ser compatível com char, um tipo inteiro assinado ou um tipo inteiro não assinado. A escolha do tipo é definida pela implementação, mas deve ser capaz de representar os valores de todos os membros da enumeração.

Não que os compiladores sejam bons em seguir o padrão, mas essencialmente: Se o seu enum tiver algo além de um int, você estará em um "comportamento não suportado profundo que pode voltar a morder você em um ano ou dois".

Michael Stum
fonte
3
tendo apenas isso, acho que o seguinte é válido: enum {LAST = INT_MAX, LAST1, LAST2}; então LAST2 não é representável em int, mas não havia uma expressão que o definisse.
Johannes Schaub - litb
4
No PDF atual, ele define que: "Os identificadores em uma lista de enumeradores são declarados como constantes que possuem o tipo int [...]". Eu omiti isso para torná-lo não muito detalhado.
Michael Stum
2
Observe " um tipo inteiro assinado ou um tipo inteiro não assinado". Não necessariamente int. shorte também longsão tipos inteiros e, independentemente da escolha da implementação, todos os valores devem se ajustar (" deve ser capaz de representar os valores de todos os membros da enumeração").
3
Notável: constante de enumeração e tipo enumerado não são a mesma coisa . O primeiro é o conteúdo da lista de declarações enum, o último é a variável real. Portanto, embora as constantes de enumeração devam ser int, a variável de enumeração real pode ser outro tipo. Essa é uma inconsistência bem conhecida no padrão.
Lundin 25/09
1
Para esclarecer o ponto de Lundin: Para enum my_enum { my_value }, my_valueterá tipo int, mas enum my_enumpode ter um tipo definido de implementação que deve representar pelo menos todos os valores de enumeração. Portanto, my_valuepode haver uma conversão restrita para enum my_enum, mas é garantido que não será excedido.
P O'Conbhui
17

Enquanto as respostas anteriores estão corretas, alguns compiladores têm opções para quebrar o padrão e usar o menor tipo que conterá todos os valores.

Exemplo com o GCC (documentação no manual do GCC ):

enum ord {
    FIRST = 1,
    SECOND,
    THIRD
} __attribute__ ((__packed__));
STATIC_ASSERT( sizeof(enum ord) == 1 )
Kevin Cox
fonte
11
Na verdade, tanto quanto posso ver, isso não quebra o padrão. Conforme explicado na resposta de Michael Stum, o padrão permite que o compilador escolha o tipo real de enumerações, desde que todos os valores sejam adequados.
sleske
2
Trabalhei com compiladores MacOS C ++ que exploram o intervalo limitado de valores em uma enumeração para armazená-los em tipos menores. Não me lembro se era Metrowerks Codewarrior ou XCode. Isso está dentro do padrão C ++. Você não pode assumir sizeof (MyEnum) == sizeof (int) em geral.
persiflage
0

Basta definir o último valor da enumeração para um valor grande o suficiente para torná-lo o tamanho que você deseja que a enumeração seja, então deve ser desse tamanho:

enum value{a=0,b,c,d,e,f,g,h,i,j,l,m,n,last=0xFFFFFFFFFFFFFFFF};
Scirdan
fonte
1
Embora esse código possa responder à pergunta, fornecer um contexto adicional sobre como e / ou por que resolve o problema melhoraria o valor a longo prazo da resposta.
leopal 15/01
-1

Não temos controle sobre o tamanho de uma enumvariável. Depende totalmente da implementação, e o compilador oferece a opção de armazenar um nome para um número inteiro usando enum, assim enumcomo o tamanho de um número inteiro.

Mehul patel
fonte
-1

Na linguagem C, um enumé garantido para ter o tamanho de um int. Há uma opção de tempo de compilação ( -fshort-enums) para torná-la tão curta (Isso é útil principalmente se os valores não ultrapassarem 64K). Não há opção de tempo de compilação para aumentar seu tamanho para 64 bits.

rashok
fonte
-6

Considere este código:

enum value{a,b,c,d,e,f,g,h,i,j,l,m,n};
value s;
cout << sizeof(s) << endl;

Dará 4 como saída. Portanto, não importa o número de elementos que um enumcontenha, seu tamanho é sempre fixo.

tushan
fonte
6
A resposta de Michael Stum está correta. Isso é específico do compilador. Você pode experimentá-lo com o IAR EWARM. IAR EWARM mostra 1 para o seu exemplo. Se houver até 255 itens, ele ainda mostra 1. Depois de adicionar o 256º item, ele aumenta para 2. #
desowin
11
A questão não é sobre C ++.
Michas
4
coisas importantes a serem realizadas antes de escrever mais C ou C ++: Só porque ele compila não significa que é legal de acordo com o Padrão. Só porque você obtém um determinado resultado, não significa que o Standard diga que você sempre fará ou que outros usuários farão quando eles executarem seu código. Perguntas como essa precisam de uma resposta que faça referência à Norma ou ao menos à especificação definida pela implementação para um determinado compilador / ABI. Simplesmente compilar e executar um programa e ver um resultado em um dia não traz nenhuma lição sobre essas questões (e muito pouco sobre qualquer outra coisa).
Underscore_d