Wie groß ist eine Aufzählung in C?

140

Ich erstelle eine Reihe von Aufzählungswerten, aber jeder Aufzählungswert muss 64 Bit breit sein. Wenn ich mich richtig erinnere, hat eine Aufzählung im Allgemeinen die gleiche Größe wie eine int; aber ich dachte, ich hätte irgendwo gelesen, dass (zumindest in GCC) der Compiler die Aufzählung beliebig breit machen kann, um ihre Werte zu halten. Ist es also möglich, eine Aufzählung mit einer Breite von 64 Bit zu haben?

Mipadi
quelle
1
Wenn ich das gut verstehe, reichen Ihnen 2 ^ 32 Aufzählungen nicht? Oder ist es ein Ausrichtungsproblem, warum müssen diese 64 statt 32 sein, ich bin sehr neugierig.
Jokoon
1
@jokoon: Ich erinnere mich ehrlich gesagt nicht mehr. Ich glaube, ich wollte, dass die Aufzählungen Werte größer als 2 ^ 32-1 enthalten.
Mipadi
Eine Verwendung wäre, wenn Sie eine Vereinigung zwischen einer Aufzählung und einem Zeiger benötigen.
Demi

Antworten:

97

An enumist garantiert nur groß genug, um intWerte aufzunehmen. Dem Compiler steht es frei, den tatsächlich verwendeten Typ basierend auf den definierten Aufzählungskonstanten auszuwählen, sodass er einen kleineren Typ auswählen kann, wenn er die von Ihnen definierten Werte darstellen kann. Wenn Sie Aufzählungskonstanten benötigen, die nicht in eine passen, müssen intSie dazu compilerspezifische Erweiterungen verwenden.

Robert Gamble
quelle
12
Ihr erster Satz scheint mit Ihrem letzten zu kollidieren. Ist die Einschränkung, dass ein enumgrößer als ein intoder kleiner sein sollte? Nach der Antwort von @MichaelStum sollte Ihr erster Satz lauten: "An enumpasst garantiert nur in einen intWert."
HaskellElephant
Als hässlicher implementierungssensitiver Hack auf zwei komplementären Plattformen (sind das heutzutage alle Systeme?) Können Sie eine Aufzählung so groß wie eine int erzwingen, indem Sie sicherstellen, dass sie negative Werte enthält. Keine empfohlene Technik.
Persiflage
7
Diese Antwort scheint darauf hinzudeuten, dass eine Aufzählung so groß ist wie eine int. Die Antwort von Michael Stum , die sich auf C99 bezieht, besagt, dass eine Aufzählung so klein sein kann wie eine char.
Frank Kusters
3
Der erste Satz dieser Antwort ist falsch. Der enumist garantiert nur groß genug, um den Wert des größten Enumerators in der Enumeration aufzunehmen.
MM
91

Entnommen aus dem aktuellen C-Standard (C99): http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf

6.7.2.2 Aufzählungsspezifizierer
[...]
Einschränkungen
Der Ausdruck, der den Wert einer Aufzählungskonstante definiert, muss ein ganzzahliger Konstantenausdruck sein, dessen Wert als int darstellbar ist.
[...]
Jeder Aufzählungstyp muss mit char, einem vorzeichenbehafteten Ganzzahltyp oder einem vorzeichenlosen Ganzzahltyp kompatibel sein. Die Wahl des Typs ist implementierungsdefiniert, muss jedoch in der Lage sein, die Werte aller Mitglieder der Aufzählung darzustellen.

Nicht, dass Compiler gut darin sind, dem Standard zu folgen, aber im Wesentlichen: Wenn Ihre Aufzählung etwas anderes als ein int enthält, befinden Sie sich in einem tiefen "nicht unterstützten Verhalten, das Sie in ein oder zwei Jahren zurückbeißen kann".

Michael Stum
quelle
3
Wenn ich nur das habe, ist folgendes gültig, denke ich: enum {LAST = INT_MAX, LAST1, LAST2}; Daher ist LAST2 in int nicht darstellbar, aber es gab keinen Ausdruck, der es definiert.
Johannes Schaub - litb
4
In der eigentlichen PDF-Datei wird Folgendes definiert: "Die Bezeichner in einer Enumeratorliste werden als Konstanten vom Typ int [...] deklariert." Ich habe das weggelassen, um es nicht zu ausführlich zu machen.
Michael Stum
2
Hinweis " Ein vorzeichenbehafteter Integer-Typ oder ein vorzeichenloser Integer-Typ". Nicht unbedingt int. shortund longsind auch ganzzahlige Typen, und unabhängig von der Auswahl der Implementierung müssen alle Werte passen (" muss in der Lage sein, die Werte aller Mitglieder der Aufzählung darzustellen").
3
Bemerkenswert: Aufzählungskonstante und Aufzählungstyp sind nicht dasselbe . Ersteres ist der Inhalt der Aufzählungsdeklarationsliste, letzteres ist die eigentliche Variable. Während also die Aufzählungskonstanten sein müssen int, könnte die tatsächliche Aufzählungsvariable ein anderer Typ sein. Dies ist eine bekannte Inkonsistenz im Standard.
Lundin
1
Um Lundins Punkt zu verdeutlichen: For enum my_enum { my_value }hat my_valueeinen Typ int, enum my_enumkann aber einen implementierungsdefinierten Typ haben, der mindestens alle Aufzählungswerte darstellen muss. Es my_valuekann also zu einer Verengung der Konvertierung kommen enum my_enum, aber es wird garantiert nicht überlaufen.
P O'Conbhui
16

Während die vorherigen Antworten korrekt sind, haben einige Compiler Optionen, um den Standard zu brechen und den kleinsten Typ zu verwenden, der alle Werte enthält.

Beispiel mit GCC (Dokumentation im GCC-Handbuch ):

enum ord {
    FIRST = 1,
    SECOND,
    THIRD
} __attribute__ ((__packed__));
STATIC_ASSERT( sizeof(enum ord) == 1 )
Kevin Cox
quelle
10
Soweit ich sehen kann, verstößt dies nicht gegen den Standard. Wie in der Antwort von Michael Stum erläutert, ermöglicht der Standard dem Compiler, den tatsächlichen Typ der Aufzählungen auszuwählen, solange alle Werte passen.
Sleske
2
Ich habe mit MacOS C ++ - Compilern gearbeitet, die den begrenzten Wertebereich in einer Aufzählung ausnutzen, um sie in kleineren Typen zu speichern. Ich kann mich nicht erinnern, ob es Metrowerks Codewarrior oder XCode war. Dies liegt im C ++ - Standard. Sie können im Allgemeinen nicht sizeof (MyEnum) == sizeof (int) annehmen.
Persiflage
0

Setzen Sie einfach den letzten Wert der Aufzählung auf einen Wert, der groß genug ist, um die Größe zu erreichen, die die Aufzählung haben soll. Dann sollte sie folgende Größe haben:

enum value{a=0,b,c,d,e,f,g,h,i,j,l,m,n,last=0xFFFFFFFFFFFFFFFF};
Scirdan
quelle
1
Während dieser Code die Frage möglicherweise beantwortet, würde die Bereitstellung eines zusätzlichen Kontexts darüber, wie und / oder warum das Problem gelöst wird, den langfristigen Wert der Antwort verbessern.
Leopal
-1

Wir haben keine Kontrolle über die Größe einer enumVariablen. Dies hängt vollständig von der Implementierung ab, und der Compiler bietet die Möglichkeit, einen Namen für eine Ganzzahl mit zu speichern enum, sodass er enumder Größe einer Ganzzahl folgt.

Mehul Patel
quelle
-1

In der C-Sprache hat ein enumgarantiert die Größe eines int. Es gibt eine Option -fshort-enumszur Kompilierungszeit ( ), um sie so kurz wie möglich zu halten (Dies ist hauptsächlich nützlich, wenn die Werte nicht mehr als 64 KB betragen). Es gibt keine Option zur Kompilierungszeit, um die Größe auf 64 Bit zu erhöhen.

Rashok
quelle
-6

Betrachten Sie diesen Code:

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

Es wird 4 als Ausgabe geben. Unabhängig von der Anzahl der enthaltenen Elemente enumist die Größe immer festgelegt.

Tushan
quelle
6
Die Antwort von Michael Stum ist richtig. Dies ist compilerspezifisch. Sie können es selbst mit IAR EWARM ausprobieren. IAR EWARM zeigt 1 für Ihr Beispiel. Wenn es bis zu 255 Elemente gibt, wird immer noch 1
angezeigt.
10
Die Frage betrifft nicht C ++.
Michas
3
Wichtige Dinge, die vor dem Schreiben von C oder C ++ zu beachten sind: Nur weil es kompiliert wird, heißt das nicht, dass es gemäß dem Standard legal ist. Nur weil Sie ein bestimmtes Ergebnis erhalten, heißt das nicht, dass der Standard dies immer oder andere Benutzer sagt, wenn sie Ihren Code ausführen. Fragen wie diese benötigen eine Antwort, die auf den Standard oder zumindest die implementierungsdefinierte Spezifikation für einen bestimmten Compiler / ABI verweist . Das einfache Kompilieren und Ausführen eines Programms und das Anzeigen eines Ergebnisses an einem Tag vermittelt keine Lektion über solche Fragen (und nur sehr wenig über irgendetwas anderes).
underscore_d