Я не думаю, що я принципово розумію, що enum
таке, і коли його використовувати.
Наприклад:
typedef enum {
kCircle,
kRectangle,
kOblateSpheroid
} ShapeType;
Що насправді декларується тут?
Я не думаю, що я принципово розумію, що enum
таке, і коли його використовувати.
Наприклад:
typedef enum {
kCircle,
kRectangle,
kOblateSpheroid
} ShapeType;
Що насправді декларується тут?
Відповіді:
Три речі оголошуються тут: анонімний перераховується типу оголошується, ShapeType
в даний час оголошений ЬурейеЕ для цього анонімного перерахування, і три імені kCircle
, kRectangle
і kOblateSpheroid
оголошуються в якості інтегральних констант.
Давайте розбимо це. У найпростішому випадку перерахування може бути оголошено як
enum tagname { ... };
Це оголошує перерахування з тегом tagname
. У C і Objective-C (але не C ++) будь-які посилання на це повинні передувати enum
ключовому слову. Наприклад:
enum tagname x; // declare x of type 'enum tagname'
tagname x; // ERROR in C/Objective-C, OK in C++
Щоб уникнути необхідності використання enum
ключового слова скрізь, можна створити typedef:
enum tagname { ... };
typedef enum tagname tagname; // declare 'tagname' as a typedef for 'enum tagname'
Це можна спростити в один рядок:
typedef enum tagname { ... } tagname; // declare both 'enum tagname' and 'tagname'
І , нарешті, якщо ми не повинні бути в змозі використати enum tagname
з enum
ключовим словом, ми можемо зробити enum
анонімне і тільки оголосити його з ім'ям ЬурейеЕ:
typedef enum { ... } tagname;
Тепер у цьому випадку ми оголошуємо ShapeType
напевне ім'я анонімного перерахування. ShapeType
насправді просто цілочисельний тип, і повинен використовуватися тільки для оголошення змінних , які утримують одне зі значень , зазначених в декларації (тобто, один з kCircle
, kRectangle
, і kOblateSpheroid
). ShapeType
Однак ви можете призначити змінній інше значення, використовуючи кастинг, тому вам слід бути обережними, читаючи значення перерахунків.
І, нарешті, kCircle
, kRectangle
і kOblateSpheroid
оголошені як інтегральні константи в глобальному просторі імен. Оскільки конкретних значень не було визначено, вони присвоюються послідовним цілим числам, починаючи з 0, так kCircle
це 0, kRectangle
дорівнює 1 і kOblateSpheroid
дорівнює 2.
Apple рекомендує визначити подібні переліки з Xcode 4.4 :
typedef enum ShapeType : NSUInteger {
kCircle,
kRectangle,
kOblateSpheroid
} ShapeType;
Вони також надають зручний макрос NS_ENUM
:
typedef NS_ENUM(NSUInteger, ShapeType) {
kCircle,
kRectangle,
kOblateSpheroid
};
Ці визначення забезпечують більш чітку перевірку типу та краще завершення коду. Я не зміг знайти офіційну документацію NS_ENUM
, але ви можете переглянути відео "Сучасний об'єктив-C" з сесії WWDC 2012 тут .
ОНОВЛЕННЯ
Посилання на офіційну документацію тут .
NS_ENUM
макросу Apple від NSHipster: NSHipster.com/ns_enum-ns_options
Користувач визначено тип , який має можливі значення kCircle
, kRectangle
чи kOblateSpheroid
. Значення всередині enum (kCircle тощо), однак, видно і поза enum. Важливо пам’ятати про це ( int i = kCircle;
дійсно, наприклад).
Оновлення для 64-розрядних змін: згідно з документами Apple про 64-бітні зміни,
Перерахування також вводяться: У компіляторі LLVM перелічені типи можуть визначати розмір перерахування. Це означає, що деякі перелічені типи також можуть мати розмір, більший, ніж ви очікували. Рішення, як і у всіх інших випадках, полягає в тому, щоб не робити припущень щодо розміру типу даних. Натомість призначте будь-які перераховані значення змінній із відповідним типом даних
Тож вам доведеться створити enum з типом нижче синтаксису, якщо ви підтримуєте 64-розрядні.
typedef NS_ENUM(NSUInteger, ShapeType) {
kCircle,
kRectangle,
kOblateSpheroid
};
або
typedef enum ShapeType : NSUInteger {
kCircle,
kRectangle,
kOblateSpheroid
} ShapeType;
В іншому випадку це призведе до попередження як Implicit conversion loses integer precision: NSUInteger (aka 'unsigned long') to ShapeType
Оновлення для швидкого програмування:
Швидко відбувається зміна синтаксису.
enum ControlButtonID: NSUInteger {
case kCircle , kRectangle, kOblateSpheroid
}
Перелічення (абревіатура перерахування) використовується для перерахування набору значень (нумераторів). Значення - це абстрактна річ, представлена символом (словом). Наприклад, базовий перелік може бути
enum { xs,s,m,l,xl,xxl,xxxl,xxxxl };
Цей перелік називається анонімним, оскільки у вас немає символу для його імені. Але це все-таки абсолютно правильно. Просто використовуйте його так
enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } myGrandMotherDressSize;
Добре. Життя прекрасне, і все йде добре. Але одного разу вам потрібно повторно використовувати цю перерахунок, щоб визначити нову змінну для зберігання myGrandFatherPantSize, тоді ви напишете:
enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } myGrandMotherDressSize;
enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } myGrandFatherPantSize;
Але тоді у вас є помилка компілятора "перезначення перелічувача". Власне, проблема полягає в тому, що компілятор не впевнений, що ви спочатку перераховуєте, а ви вдруге описуєте те саме.
Тоді, якщо ви хочете повторно використовувати той самий набір нумераторів (тут xs ... xxxxl) у кількох місцях, ви повинні позначити його унікальним іменем. Вдруге, коли ви використовуєте цей набір, ви просто повинні використовувати тег. Але не забувайте, що цей тег не замінює слово enum, а лише набір нумераторів. Тоді подбайте про використання енту як завжди. Подобається це:
// 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;
ви також можете використовувати його у визначенні параметрів:
// Observe that here, I still use the enum
- (void) buyANewDressToMyGrandMother:(enum sizes)theSize;
Можна сказати, що переписування переписок скрізь не є зручним, і код виглядає дещо дивно. Ти правий. Реальний тип був би кращим.
Це завершальний крок нашого великого прогресу до саміту. Просто додавши typedef, давайте перетворимо наш перерахунок у реальний тип. О останнє, typedef не дозволений у вашому класі. Потім визначте свій тип трохи вище. Зробіть так:
// enum definition
enum sizes { xs,s,m,l,xl,xxl,xxxl,xxxxl };
typedef enum sizes size_type
@interface myClass {
...
size_type myGrandMotherDressSize, myGrandFatherPantSize;
...
}
Пам'ятайте, що тег необов’язковий. Тоді оскільки тут, у такому випадку, ми не тегуємо нумератори, а просто для визначення нового типу. Тоді нам це вже не потрібно.
// enum definition
typedef enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } size_type;
@interface myClass : NSObject {
...
size_type myGrandMotherDressSize, myGrandFatherPantSize;
...
}
@end
Якщо ви розвиваєтеся в Objective-C з XCode, я дозволяю вам відкрити кілька приємних макросів з префіксом NS_ENUM. Це повинно допомогти вам легко визначити хороші перерахунки, і, крім того, допоможе статичному аналізатору зробити кілька цікавих перевірок перед тим, як компілювати.
Добрий Енум!
typedef
є корисним для перевизначення імені існуючого типу змінної. Це забезпечує короткий та змістовний спосіб викликати тип даних. наприклад:
typedef unsigned long int TWOWORDS;
тут тип неподписаного довгого int переосмислюється як тип TWOWORDS. Таким чином, тепер ми можемо оголошувати змінні типу без підпису long int, записуючи,
TWOWORDS var1, var2;
замість
unsigned long int var1, var2;
typedef enum {
kCircle,
kRectangle,
kOblateSpheroid
} ShapeType;
тоді ви можете використовувати його так:
ShapeType shape;
і
enum {
kCircle,
kRectangle,
kOblateSpheroid
}
ShapeType;
тепер ви можете використовувати його так: -
enum ShapeType shape;
enum використовується для присвоєння значень елементам enum, що неможливо зробити в структура. Тому щоразу замість доступу до повної змінної ми можемо це робити за значенням, яке ми присвоюємо змінним в enum. За замовчуванням він починається з 0 присвоєння, але ми можемо призначити йому будь-яке значення, а наступній змінній в enum буде присвоєно значення попереднього значення +1.
Ви можете використовувати у наведеному нижче форматі, неочищене значення за замовчуванням, починаючи з 0, так
Ви можете призначити власне конкретне початкове значення.
typedef enum : NSUInteger {
kCircle, // for your value; kCircle = 5, ...
kRectangle,
kOblateSpheroid
} ShapeType;
ShapeType circleShape = kCircle;
NSLog(@"%lu", (unsigned long) circleShape); // prints: 0
Typedef дозволяє програмісту визначити один тип Objective-C як інший. Наприклад,
typedef int Counter; визначає тип Counter, який є еквівалентним типу int. Це різко покращує читабельність коду.
Typedef - це ключове слово на C і C ++. Він використовується для створення нових імен для основних типів даних (char, int, float, double, struct & enum) .
typedef enum {
kCircle,
kRectangle,
kOblateSpheroid
} ShapeType;
Тут створюються перелічені типи даних ShapeType, і ми можемо записати нові імена для enum типу ShapeType, як наведено нижче
ShapeType shape1;
ShapeType shape2;
ShapeType shape3;
enum може зменшити багато типів "помилок" і зробити код більш керованим
#define STATE_GOOD 0
#define STATE_BAD 1
#define STATE_OTHER 2
int STATE = STATE_OTHER
Визначення не має обмежень. Це просто лише заміна. Він не в змозі обмежити всі умови держави. Коли STATE присвоєно 5, програма буде помилятися, оскільки немає відповідного стану. Але компілятор не збирається попереджати STATE = 5
Тож краще використовувати так
typedef enum SampleState {
SampleStateGood = 0,
SampleStateBad,
SampleStateOther
} SampleState;
SampleState state = SampleStateGood;