Почему какао не везде использует один и тот же стиль декларации enum? - PullRequest
12 голосов
/ 11 февраля 2010

Мне было интересно, в чем причина различных стилей объявления enum на какао?

Как это:

enum { constants.. }; typedef NSUInteger sometype;

Является ли причиной использование typedef, чтобы заставить задания работать в NSUInteger без приведения?

Иногда typedef - это NSInteger / NSUInteger, почему бы не использовать NSInteger всегда? Есть ли реальная выгода от использования NSUInteger?

Имена тэгов по-прежнему используются иногда, например здесь в _NSByteOrder.

Этот ответ также был очень полезен: Что такое перечисление типов в Objective-C? .

Ответы [ 3 ]

12 голосов
/ 12 февраля 2010

Несколько причин:

Причина 1: Гибкость:

enum lickahoctor { yes = 0, no = 1, maybe = 2 };

объявляет перечисление. Вы можете использовать значения yes, no и maybe в любом месте и назначать их для любого целочисленного типа. Вы также можете использовать это как тип, написав

enum lickahoctor myVar = yes;

Это хорошо, потому что если функция принимает параметр с типом enum lickahoctor, вы будете знать, что вы можете присвоить ему yes, no или maybe. Кроме того, отладчик будет знать, поэтому он будет отображать символическое имя вместо числового значения. Проблема в том, что компилятор позволит вам присваивать значения, которые вы определили в enum lickahoctor, myVar. Например, если вы хотите определить несколько флагов в базовом классе, а затем добавить еще несколько флагов в подкласс, вы не сможете сделать это таким образом.

Если вместо этого вы используете int, у вас нет этой проблемы. Итак, вы хотите использовать какой-то тип int, чтобы вы могли назначать произвольные константы.

Причина 2: двоичная совместимость:

Компилятор выбирает хороший размер, который соответствует всем константам, которые вы определили в перечислении. Там нет никакой гарантии, что вы получите. Таким образом, если вы записываете структуру, содержащую такую ​​переменную, непосредственно в файл, нет гарантии, что она будет иметь тот же размер, когда вы будете читать ее в следующей версии вашего приложения (по крайней мере, в соответствии со стандартом C - - это не так уж и плохо на практике).

Если вместо этого вы используете какой-то тип int, платформа обычно гарантирует определенный размер для этого числа. Особенно, если вы используете один из типов, которые гарантированно имеют определенный размер, например int32_t / uint32_t.

Причина 3: удобочитаемость и самостоятельная документация

Когда вы объявляете myVar выше, сразу становится ясно, какие значения вы можете в него добавить. Если вы просто используете int или uint32_t, это не так. Итак, что вы делаете, вы используете

enum { yes, no, maybe };
typedef uint32_t lickahoctor;

для определения подходящего имени для целого числа где-то рядом с константами, которое будет напоминать людям, что переменная этого типа может содержать это значение. Но вы все равно получаете преимущество предсказуемого фиксированного размера и возможности определять дополнительные значения в подклассах, если это необходимо.

Причина 4: поддержка битовых полей

Переменные с типом enum поддерживают только одно значение из их параметров. Поэтому, если вы пытаетесь реализовать битовое поле, вы не можете ввести его как битовое поле. Кроме того, вам нужно использовать переменные без знака, чтобы избежать расширения кода от вас.

2 голосов
/ 12 февраля 2010

Является ли причиной использовать typedef для получения назначения в NSUInteger для работы без литья?

typedef используется для указания базового типа для значений перечисления. Вы можете всегда приводить значение перечисления к другому типу до тех пор, пока оно усекается, путем приведения к меньшему типу (от NSUInteger до unsigned short).

NSInteger и NSUInteger были введены для упрощения миграции приложений на 64 бита, предоставляя независимый от архитектуры / платформы тип для целых чисел со знаком и без знака. Таким образом, независимо от того, сколько бит имеет процессор, приложения не нужно переписывать.

Иногда typedef является одним из NSInteger / NSUInteger, почему бы не использовать NSInteger всегда? Есть ли настоящий польза от NSUInteger?

Выбор зависит от значений в перечислении. Некоторые перечисления имеют много значений, поэтому им нужны все доступные биты:

  • NSInteger предлагает 2 ^ 31 положительных и отрицательных значений (для 32-битной архитектуры).
  • NSUInteger предлагает 2 ^ 32 положительных значения (для 32-битной архитектуры).
  • Если перечисление должно содержать только положительные значения, используйте NSUInteger.
  • Если ваше перечисление должно содержать как положительные, так и отрицательные значения, используйте NSInteger.
  • NSUInteger обычно используется для перечисления флагов, так как он предоставляет 32 различных значения (в 32-битной архитектуре) для объединения по желанию.

Я не знаю, есть ли правило выбора в команде разработчиков Apple для этого. Я надеюсь на это ...

1 голос
/ 12 февраля 2010

Пока вы можете использовать что-то вроде

  typedef enum { constants... } sometype;

нет никакой гарантии относительно возможного размера битов типа данных. Ну, это не совсем верно, но это правда. Лучше, чтобы API определялись в конкретных размерах данных, чем с чем-то, что может меняться в зависимости от используемых настроек компилятора.

...