Qual è la dimensione di un enum in C?


140

Sto creando un insieme di valori enum, ma ho bisogno che ciascun valore enum sia largo 64 bit. Se ricordo bene, un enum ha generalmente le stesse dimensioni di un int; ma ho pensato di leggere da qualche parte che (almeno in GCC) il compilatore può fare in modo che l'enum sia la larghezza necessaria per mantenere i loro valori. Quindi, è possibile avere un enum che è largo 64 bit?


1
Quindi, se ho capito bene, 2 ^ 32 enumerazioni non sono sufficienti per te? O è una preoccupazione di allineamento, perché hai bisogno che siano 64 anziché 32, sono molto curioso.
jokoon

1
@jokoon: sinceramente non mi ricordo più. Penso di volere che gli enumeri contengano valori maggiori di 2 ^ 32-1.
mipadi,

Un uso sarebbe se avessi bisogno di un'unione tra un enum e un puntatore.
Demi

Risposte:


97

An enumè garantito per essere sufficientemente grande da contenere intvalori. Il compilatore è libero di scegliere il tipo effettivo utilizzato in base alle costanti di enumerazione definite in modo da poter scegliere un tipo più piccolo se può rappresentare i valori definiti. Se hai bisogno di costanti di enumerazione che non rientrano in un int, dovrai utilizzare estensioni specifiche del compilatore per farlo.


12
La tua prima frase sembra essere in conflitto con la tua ultima. Il vincolo che an enumdovrebbe essere più grande di into più piccolo? Dopo la risposta di @MichaelStum la tua prima frase dovrebbe essere "An enumè garantito solo per adattarsi a un intvalore".
HaskellElephant

Come brutto trucco sensibile all'implementazione su due piattaforme complementari (è che tutti i sistemi in questi giorni?), Puoi forzare un enum a essere grande come un int assicurandoti che contenga valori negativi. Tuttavia, non è una tecnica consigliata.
persiflage,

7
Questa risposta sembra suggerire che un enum è grande come un int. La risposta di Michael Stum , che fa riferimento C99, dice che un enum può essere piccolo come un char.
Frank Kusters,

3
La prima frase di questa risposta non è corretta. È enumgarantito che sia sufficientemente grande da contenere il valore del più grande enumeratore nell'enum.
MM

91

Tratto dall'attuale standard C (C99): http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf

6.7.2.2 Vincoli agli identificatori dell'enumerazione
[...] L'espressione che definisce il valore di una costante di enumerazione deve essere un'espressione di una costante intera che ha un valore rappresentabile come int. [...] Ciascun tipo elencato deve essere compatibile con char, un tipo intero con segno o un tipo intero senza segno. La scelta del tipo è definita dall'implementazione, ma deve essere in grado di rappresentare i valori di tutti i membri dell'enumerazione.



Non che i compilatori siano bravi a seguire lo standard, ma essenzialmente: se il tuo enum contiene qualcosa di diverso da un int, sei in un profondo "comportamento non supportato che potrebbe tornare a morderti in un anno o due" territorio.


3
avendo solo quello, penso che sia valido credo: enum {LAST = INT_MAX, LAST1, LAST2}; quindi LAST2 non è rappresentabile in int, ma non c'era un'espressione che lo definiva.
Johannes Schaub - litb

4
Nel PDF effettivo definisce che: "Gli identificatori in un elenco di enumeratori sono dichiarati come costanti che hanno il tipo int [...]". L'ho omesso per renderlo non troppo dettagliato.
Michael Stum

2
Nota " un tipo intero con segno o un tipo intero senza segno". Non necessariamente int. shorte longsono anche tipi interi, e qualunque sia l'implementazione scelta, tutti i valori devono adattarsi (" devono essere in grado di rappresentare i valori di tutti i membri dell'enumerazione").

3
Notevole: la costante di enumerazione e il tipo enumerato non sono la stessa cosa . I primi sono i contenuti dell'elenco delle dichiarazioni enum, il secondo è la variabile effettiva. Pertanto, mentre le costanti di enumerazione devono essere int, la variabile di enumerazione effettiva potrebbe essere un altro tipo. Questa è un'incoerenza ben nota nello standard.
Lundin,

1
Per chiarire il punto di Lundin: For enum my_enum { my_value }, my_valueavrà tipo int, ma enum my_enumpuò avere un tipo definito di implementazione che deve almeno rappresentare tutti i valori di enumerazione. Quindi my_valuepotrebbe avere una conversione restrittiva in enum my_enum, ma è garantito che non trabocchi.
P O'Conbhui,

17

Mentre le risposte precedenti sono corrette, alcuni compilatori hanno opzioni per infrangere lo standard e utilizzare il tipo più piccolo che conterrà tutti i valori.

Esempio con GCC (documentazione nel Manuale GCC ):

enum ord {
    FIRST = 1,
    SECOND,
    THIRD
} __attribute__ ((__packed__));
STATIC_ASSERT( sizeof(enum ord) == 1 )

11
In realtà, per quanto posso vedere, questo non infrange lo standard. Come spiegato nella risposta di Michael Stum, lo standard consente al compilatore di scegliere il tipo effettivo di enum, purché tutti i valori si adattino.
sleske,

2
Ho lavorato con compilatori MacOS C ++ che sfruttano la gamma limitata di valori in un enum per archiviarli in tipi più piccoli. Non ricordo se fosse Metrowerks Codewarrior o XCode. Questo è all'interno dello standard C ++. Non puoi assumere sizeof (MyEnum) == sizeof (int) in generale.
persiflage,

0

Basta impostare l'ultimo valore dell'enum su un valore abbastanza grande da renderlo la dimensione che vorresti fosse l'enum, quindi dovrebbe essere quella dimensione:

enum value{a=0,b,c,d,e,f,g,h,i,j,l,m,n,last=0xFFFFFFFFFFFFFFFF};

2
Sebbene questo codice possa rispondere alla domanda, fornire un contesto aggiuntivo riguardo a come e / o perché risolve il problema migliorerebbe il valore a lungo termine della risposta.
leopale il

-1

Non abbiamo alcun controllo sulla dimensione di una enumvariabile. Dipende totalmente dall'implementazione e il compilatore dà la possibilità di memorizzare un nome per un numero intero usando enum, quindi enumsta seguendo le dimensioni di un numero intero.


-1

Nel linguaggio C, enumè garantito che abbia le dimensioni di un int. C'è un'opzione di compilazione ( -fshort-enums) per renderla breve (Ciò è utile soprattutto nel caso in cui i valori non siano più di 64 KB). Non esiste un'opzione di tempo di compilazione per aumentare le dimensioni a 64 bit.


-6

Considera questo codice:

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

Darà 4 come output. Quindi, indipendentemente dal numero di elementi che enumcontiene, la sua dimensione è sempre fissa.


6
La risposta di Michael Stum è corretta. Questo è specifico del compilatore. Puoi provarlo tu stesso con IAR EWARM. IAR EWARM mostra 1 per il tuo esempio. Se ci sono fino a 255 elementi che mostrano ancora 1. Dopo aver aggiunto il 256 ° oggetto, si sale a 2.
desowin

11
La domanda non riguarda C ++.
Michas,

4
cose importanti da realizzare prima di scrivere altri C o C ++: solo perché si compila non significa che sia legale secondo lo Standard. Solo perché ottieni un determinato risultato non significa che lo Standard dice che lo farai sempre o che lo faranno altri utenti quando eseguono il tuo codice. Domande come questa richiedono una risposta che faccia riferimento allo Standard o almeno alle specifiche definite dall'implementazione per un determinato compilatore / ABI. Semplicemente compilando ed eseguendo un programma e vedendo un risultato in un giorno non viene fornita alcuna lezione su tali domande (e molto poco su qualsiasi altra cosa).
underscore_d
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.