Я не думаю, що я принципово розумію, що 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;