Ich glaube nicht, dass ich grundlegend verstehe, was ein enum
ist und wann ich es verwenden soll.
Zum Beispiel:
typedef enum {
kCircle,
kRectangle,
kOblateSpheroid
} ShapeType;
Was wird hier wirklich deklariert?
Ich glaube nicht, dass ich grundlegend verstehe, was ein enum
ist und wann ich es verwenden soll.
Zum Beispiel:
typedef enum {
kCircle,
kRectangle,
kOblateSpheroid
} ShapeType;
Was wird hier wirklich deklariert?
Antworten:
Drei Dinge werden hier erklärt: ein anonymer Aufzählungstyp deklariert wird, ShapeType
ist für die anonyme Aufzählung ein typedef deklariert werden und die drei Namen kCircle
, kRectangle
und kOblateSpheroid
werden als integrale Konstanten deklariert.
Lassen Sie uns das aufschlüsseln. Im einfachsten Fall kann eine Aufzählung als deklariert werden
enum tagname { ... };
Dies deklariert eine Aufzählung mit dem Tag tagname
. In C und Objective-C (aber nicht C ++), alle Verweise auf diese muss mit dem vorangestellt sein enum
Stichwort. Zum Beispiel:
enum tagname x; // declare x of type 'enum tagname'
tagname x; // ERROR in C/Objective-C, OK in C++
Um zu vermeiden, dass das enum
Schlüsselwort überall verwendet werden muss, kann ein typedef erstellt werden:
enum tagname { ... };
typedef enum tagname tagname; // declare 'tagname' as a typedef for 'enum tagname'
Dies kann in einer Zeile vereinfacht werden:
typedef enum tagname { ... } tagname; // declare both 'enum tagname' and 'tagname'
Und schließlich, wenn wir nicht in der Lage sein müssen, enum tagname
das enum
Schlüsselwort zu verwenden, können wir das enum
anonymisieren und es nur mit dem typedef-Namen deklarieren:
typedef enum { ... } tagname;
In diesem Fall erklären wir, dass es ShapeType
sich um einen typisierten Namen einer anonymen Aufzählung handelt. ShapeType
ist wirklich nur ein integraler Typ, und nur Variablen verwendet werden soll , zu erklären , die in der Erklärung genannten einen des Wertes halten (das heißt, einer der kCircle
, kRectangle
und kOblateSpheroid
). Sie können einer ShapeType
Variablen jedoch einen anderen Wert zuweisen , indem Sie sie umwandeln. Daher müssen Sie beim Lesen von Aufzählungswerten vorsichtig sein.
Schließlich kCircle
, kRectangle
und kOblateSpheroid
als integrale Konstanten im globalen Namespace deklariert. Da keine spezifischen Werte angegeben wurden, werden sie aufeinanderfolgenden Ganzzahlen zugewiesen, die mit 0 beginnen, also kCircle
0, kRectangle
1 und kOblateSpheroid
2.
Apple empfiehlt, solche Aufzählungen seit Xcode 4.4 zu definieren :
typedef enum ShapeType : NSUInteger {
kCircle,
kRectangle,
kOblateSpheroid
} ShapeType;
Sie bieten auch ein praktisches Makro NS_ENUM
:
typedef NS_ENUM(NSUInteger, ShapeType) {
kCircle,
kRectangle,
kOblateSpheroid
};
Diese Definitionen bieten eine stärkere Typprüfung und eine bessere Code-Vervollständigung. Ich konnte keine offizielle Dokumentation finden NS_ENUM
, aber Sie können das Video "Modern Objective-C" von der WWDC 2012-Sitzung hier ansehen .
UPDATE
Link zur offiziellen Dokumentation hier .
NS_ENUM
Makro durch NSHipster: NSHipster.com/ns_enum-ns_options
Ein Benutzer definierten Typ, die die möglichen Werte hat kCircle
, kRectangle
oder kOblateSpheroid
. Die Werte innerhalb der Aufzählung (kCircle usw.) sind jedoch außerhalb der Aufzählung sichtbar. Es ist wichtig, dies zu berücksichtigen ( int i = kCircle;
gilt zum Beispiel).
Update für 64-Bit-Änderung: Laut Apple-Dokumenten über 64-Bit-Änderungen,
Aufzählungen werden ebenfalls eingegeben: Im LLVM-Compiler können Aufzählungstypen die Größe der Aufzählung definieren. Dies bedeutet, dass einige aufgezählte Typen möglicherweise auch eine größere Größe haben als erwartet. Die Lösung besteht, wie in allen anderen Fällen, darin, keine Annahmen über die Größe eines Datentyps zu treffen. Weisen Sie stattdessen einer Variablen mit dem richtigen Datentyp alle aufgezählten Werte zu
Sie müssen also eine Aufzählung mit dem folgenden Syntax erstellen, wenn Sie 64-Bit unterstützen.
typedef NS_ENUM(NSUInteger, ShapeType) {
kCircle,
kRectangle,
kOblateSpheroid
};
oder
typedef enum ShapeType : NSUInteger {
kCircle,
kRectangle,
kOblateSpheroid
} ShapeType;
Andernfalls wird eine Warnung als angezeigt Implicit conversion loses integer precision: NSUInteger (aka 'unsigned long') to ShapeType
Update für die schnelle Programmierung:
In Kürze gibt es eine Syntaxänderung.
enum ControlButtonID: NSUInteger {
case kCircle , kRectangle, kOblateSpheroid
}
Die Aufzählung (Abkürzung für Aufzählung) wird verwendet, um eine Reihe von Werten (Aufzählungen) aufzulisten. Ein Wert ist eine abstrakte Sache, die durch ein Symbol (ein Wort) dargestellt wird. Zum Beispiel könnte eine Grundaufzählung sein
enum { xs,s,m,l,xl,xxl,xxxl,xxxxl };
Diese Aufzählung wird anonym genannt, da Sie kein Symbol haben, um sie zu benennen. Aber es ist immer noch vollkommen richtig. Verwenden Sie es einfach so
enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } myGrandMotherDressSize;
OK. Das Leben ist schön und alles geht gut. Aber eines Tages müssen Sie diese Aufzählung wiederverwenden, um eine neue Variable zum Speichern von myGrandFatherPantSize zu definieren. Dann schreiben Sie:
enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } myGrandMotherDressSize;
enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } myGrandFatherPantSize;
Aber dann haben Sie einen Compilerfehler "Neudefinition des Enumerators". Tatsächlich besteht das Problem darin, dass der Compiler nicht sicher ist, ob Sie zuerst aufzählen und als Zweites dasselbe beschreiben.
Wenn Sie dann denselben Satz von Enumeratoren (hier xs ... xxxxl) an mehreren Stellen wiederverwenden möchten, müssen Sie ihn mit einem eindeutigen Namen versehen. Wenn Sie dieses Set zum zweiten Mal verwenden, müssen Sie nur das Tag verwenden. Vergessen Sie jedoch nicht, dass dieses Tag nicht das Enum-Wort ersetzt, sondern nur die Enumeratoren. Achten Sie dann darauf, enum wie gewohnt zu verwenden. So was:
// Here the first use of my enum
enum sizes { xs,s,m,l,xl,xxl,xxxl,xxxxl } myGrandMotherDressSize;
// here the second use of my enum. It works now!
enum sizes myGrandFatherPantSize;
Sie können es auch in einer Parameterdefinition verwenden:
// Observe that here, I still use the enum
- (void) buyANewDressToMyGrandMother:(enum sizes)theSize;
Man könnte sagen, dass das Umschreiben von Enum überall nicht bequem ist und den Code etwas seltsam aussehen lässt. Du hast recht. Ein echter Typ wäre besser.
Dies ist der letzte Schritt unseres großen Fortschritts zum Gipfel. Durch einfaches Hinzufügen eines Typedef können wir unsere Aufzählung in einen echten Typ umwandeln. Oh das Letzte, typedef ist in deiner Klasse nicht erlaubt. Definieren Sie dann Ihren Typ direkt oben. Mach es so:
// enum definition
enum sizes { xs,s,m,l,xl,xxl,xxxl,xxxxl };
typedef enum sizes size_type
@interface myClass {
...
size_type myGrandMotherDressSize, myGrandFatherPantSize;
...
}
Denken Sie daran, dass das Tag optional ist. Dann kennzeichnen wir in diesem Fall die Enumeratoren nicht, sondern nur, um einen neuen Typ zu definieren. Dann brauchen wir es nicht mehr wirklich.
// enum definition
typedef enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } size_type;
@interface myClass : NSObject {
...
size_type myGrandMotherDressSize, myGrandFatherPantSize;
...
}
@end
Wenn Sie in Objective-C mit XCode entwickeln, können Sie einige nette Makros entdecken, denen NS_ENUM vorangestellt ist. Dies sollte Ihnen helfen, gute Aufzählungen einfach zu definieren, und hilft dem statischen Analysator außerdem, einige interessante Überprüfungen für Sie durchzuführen, bevor Sie sie kompilieren.
Gute Aufzählung!
typedef
ist nützlich, um den Namen eines vorhandenen Variablentyps neu zu definieren. Es bietet eine kurze und sinnvolle Möglichkeit, einen Datentyp aufzurufen. z.B:
typedef unsigned long int TWOWORDS;
Hier wird der Typ unsigned long int neu definiert, um vom Typ TWOWORDS zu sein. Somit können wir jetzt Variablen vom Typ unsigned long int deklarieren, indem wir schreiben:
TWOWORDS var1, var2;
anstatt
unsigned long int var1, var2;
typedef enum {
kCircle,
kRectangle,
kOblateSpheroid
} ShapeType;
dann können Sie es verwenden wie: -
ShapeType shape;
und
enum {
kCircle,
kRectangle,
kOblateSpheroid
}
ShapeType;
Jetzt können Sie es verwenden wie: -
enum ShapeType shape;
enum wird verwendet, um enum-Elementen einen Wert zuzuweisen, was in struct nicht möglich ist. Anstatt auf die vollständige Variable zuzugreifen, können wir dies jedes Mal anhand des Werts tun, den wir den Variablen in enum zuweisen. Standardmäßig beginnt es mit der Zuweisung 0, aber wir können ihm einen beliebigen Wert zuweisen, und der nächsten Variablen in enum wird ein Wert zugewiesen, der dem vorherigen Wert +1 entspricht.
Sie können im folgenden Format den Raw-Standardwert ab 0 verwenden
Sie können Ihren eigenen spezifischen Startwert zuweisen.
typedef enum : NSUInteger {
kCircle, // for your value; kCircle = 5, ...
kRectangle,
kOblateSpheroid
} ShapeType;
ShapeType circleShape = kCircle;
NSLog(@"%lu", (unsigned long) circleShape); // prints: 0
Mit einem typedef kann der Programmierer einen Objective-C-Typ als einen anderen definieren. Zum Beispiel,
typedef int Counter; Definiert den Typ Counter so, dass er dem int-Typ entspricht. Dies verbessert die Lesbarkeit des Codes drastisch.
Das Typedef ist ein Schlüsselwort in C und C ++. Es wird verwendet, um neue Namen für grundlegende Datentypen (char, int, float, double, struct & enum) zu erstellen .
typedef enum {
kCircle,
kRectangle,
kOblateSpheroid
} ShapeType;
Hier wird der aufgezählte Datentyp ShapeType erstellt und wir können neue Namen für den Aufzählungstyp ShapeType schreiben, wie unten angegeben
ShapeType shape1;
ShapeType shape2;
ShapeType shape3;
enum kann viele Arten von "Fehlern" reduzieren und den Code übersichtlicher machen
#define STATE_GOOD 0
#define STATE_BAD 1
#define STATE_OTHER 2
int STATE = STATE_OTHER
Die Definition unterliegt keinen Einschränkungen. Es ist einfach nur eine Substitution. Es ist nicht in der Lage, alle Bedingungen des Staates einzuschränken. Wenn der STATE 5 zugewiesen ist, ist das Programm falsch, da kein übereinstimmender Status vorliegt. Der Compiler wird STATE = 5 jedoch nicht warnen
Es ist also besser, so zu verwenden
typedef enum SampleState {
SampleStateGood = 0,
SampleStateBad,
SampleStateOther
} SampleState;
SampleState state = SampleStateGood;